diff --git a/.gitignore b/.gitignore index 18cea60..8f00e2e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ /poppler-test-2018-12-18-45f55f1e03b9bf3fbd334c31776b6f5e472889ec.tar.xz /poppler-0.84.0.tar.xz /poppler-0.90.0.tar.xz +/poppler-test-2021-01-11-03a4b9eb854a06a83c465e82de601796c458bbe9.tar.xz +/poppler-21.01.0.tar.xz diff --git a/0001-Revert-Remove-the-Qt4-frontend.patch b/0001-Revert-Remove-the-Qt4-frontend.patch deleted file mode 100644 index ecafbd7..0000000 --- a/0001-Revert-Remove-the-Qt4-frontend.patch +++ /dev/null @@ -1,26570 +0,0 @@ -From 017d466e5d0895504fc8711f87806d3bd08d8416 Mon Sep 17 00:00:00 2001 -From: David Tardon -Date: Thu, 8 Feb 2018 19:13:01 +0100 -Subject: [PATCH] Revert "Remove the Qt4 frontend" - -This reverts commit fb4c69d270a618bb23791e52f46ec73c86574294. ---- - .gitignore | 2 + - CMakeLists.txt | 17 + - cmake/modules/FindQt4.cmake | 1311 +++++++ - poppler-qt4.pc.cmake | 12 + - qt4/.gitignore | 4 + - qt4/CMakeLists.txt | 6 + - qt4/demos/.gitignore | 4 + - qt4/demos/CMakeLists.txt | 28 + - qt4/demos/abstractinfodock.cpp | 57 + - qt4/demos/abstractinfodock.h | 48 + - qt4/demos/documentobserver.cpp | 50 + - qt4/demos/documentobserver.h | 50 + - qt4/demos/embeddedfiles.cpp | 82 + - qt4/demos/embeddedfiles.h | 44 + - qt4/demos/fonts.cpp | 72 + - qt4/demos/fonts.h | 43 + - qt4/demos/info.cpp | 72 + - qt4/demos/info.h | 43 + - qt4/demos/main_viewer.cpp | 33 + - qt4/demos/metadata.cpp | 50 + - qt4/demos/metadata.h | 43 + - qt4/demos/navigationtoolbar.cpp | 144 + - qt4/demos/navigationtoolbar.h | 65 + - qt4/demos/optcontent.cpp | 69 + - qt4/demos/optcontent.h | 47 + - qt4/demos/pageview.cpp | 101 + - qt4/demos/pageview.h | 53 + - qt4/demos/permissions.cpp | 66 + - qt4/demos/permissions.h | 43 + - qt4/demos/thumbnails.cpp | 84 + - qt4/demos/thumbnails.h | 48 + - qt4/demos/toc.cpp | 88 + - qt4/demos/toc.h | 43 + - qt4/demos/viewer.cpp | 319 ++ - qt4/demos/viewer.h | 73 + - qt4/src/.gitignore | 9 + - qt4/src/ArthurOutputDev.cc | 812 ++++ - qt4/src/ArthurOutputDev.h | 170 + - qt4/src/CMakeLists.txt | 54 + - qt4/src/Doxyfile | 1637 +++++++++ - qt4/src/Mainpage.dox | 85 + - qt4/src/poppler-annotation-helper.h | 181 + - qt4/src/poppler-annotation-private.h | 112 + - qt4/src/poppler-annotation.cc | 5089 ++++++++++++++++++++++++++ - qt4/src/poppler-annotation.h | 1375 +++++++ - qt4/src/poppler-base-converter.cc | 105 + - qt4/src/poppler-converter-private.h | 49 + - qt4/src/poppler-document.cc | 850 +++++ - qt4/src/poppler-embeddedfile-private.h | 42 + - qt4/src/poppler-embeddedfile.cc | 135 + - qt4/src/poppler-export.h | 20 + - qt4/src/poppler-fontinfo.cc | 150 + - qt4/src/poppler-form.cc | 416 +++ - qt4/src/poppler-form.h | 343 ++ - qt4/src/poppler-link-extractor-private.h | 57 + - qt4/src/poppler-link-extractor.cc | 84 + - qt4/src/poppler-link-private.h | 57 + - qt4/src/poppler-link.cc | 710 ++++ - qt4/src/poppler-link.h | 641 ++++ - qt4/src/poppler-media.cc | 168 + - qt4/src/poppler-media.h | 100 + - qt4/src/poppler-movie.cc | 110 + - qt4/src/poppler-optcontent-private.h | 124 + - qt4/src/poppler-optcontent.cc | 456 +++ - qt4/src/poppler-optcontent.h | 84 + - qt4/src/poppler-page-private.h | 57 + - qt4/src/poppler-page-transition-private.h | 28 + - qt4/src/poppler-page-transition.cc | 101 + - qt4/src/poppler-page-transition.h | 158 + - qt4/src/poppler-page.cc | 810 ++++ - qt4/src/poppler-pdf-converter.cc | 115 + - qt4/src/poppler-private.cc | 296 ++ - qt4/src/poppler-private.h | 241 ++ - qt4/src/poppler-ps-converter.cc | 280 ++ - qt4/src/poppler-qiodeviceoutstream-private.h | 47 + - qt4/src/poppler-qiodeviceoutstream.cc | 64 + - qt4/src/poppler-qt4.h | 1990 ++++++++++ - qt4/src/poppler-sound.cc | 132 + - qt4/src/poppler-textbox.cc | 63 + - qt4/tests/.gitignore | 33 + - qt4/tests/CMakeLists.txt | 67 + - qt4/tests/README.unittest | 23 + - qt4/tests/check_actualtext.cpp | 33 + - qt4/tests/check_attachments.cpp | 157 + - qt4/tests/check_dateConversion.cpp | 142 + - qt4/tests/check_fonts.cpp | 248 ++ - qt4/tests/check_goostring.cpp | 127 + - qt4/tests/check_lexer.cpp | 107 + - qt4/tests/check_links.cpp | 98 + - qt4/tests/check_metadata.cpp | 275 ++ - qt4/tests/check_optcontent.cpp | 446 +++ - qt4/tests/check_pagelabelinfo.cpp | 43 + - qt4/tests/check_pagelayout.cpp | 49 + - qt4/tests/check_pagemode.cpp | 73 + - qt4/tests/check_password.cpp | 88 + - qt4/tests/check_permissions.cpp | 44 + - qt4/tests/check_search.cpp | 175 + - qt4/tests/check_strings.cpp | 250 ++ - qt4/tests/poppler-attachments.cpp | 39 + - qt4/tests/poppler-fonts.cpp | 89 + - qt4/tests/poppler-forms.cpp | 166 + - qt4/tests/poppler-texts.cpp | 40 + - qt4/tests/stress-poppler-dir.cpp | 67 + - qt4/tests/stress-poppler-qt4.cpp | 74 + - qt4/tests/stress-threads-qt4.cpp | 309 ++ - qt4/tests/test-password-qt4.cpp | 136 + - qt4/tests/test-poppler-qt4.cpp | 235 ++ - qt4/tests/test-render-to-file.cpp | 69 + - 108 files changed, 25623 insertions(+) - create mode 100644 cmake/modules/FindQt4.cmake - create mode 100644 poppler-qt4.pc.cmake - create mode 100644 qt4/.gitignore - create mode 100644 qt4/CMakeLists.txt - create mode 100644 qt4/demos/.gitignore - create mode 100644 qt4/demos/CMakeLists.txt - create mode 100644 qt4/demos/abstractinfodock.cpp - create mode 100644 qt4/demos/abstractinfodock.h - create mode 100644 qt4/demos/documentobserver.cpp - create mode 100644 qt4/demos/documentobserver.h - create mode 100644 qt4/demos/embeddedfiles.cpp - create mode 100644 qt4/demos/embeddedfiles.h - create mode 100644 qt4/demos/fonts.cpp - create mode 100644 qt4/demos/fonts.h - create mode 100644 qt4/demos/info.cpp - create mode 100644 qt4/demos/info.h - create mode 100644 qt4/demos/main_viewer.cpp - create mode 100644 qt4/demos/metadata.cpp - create mode 100644 qt4/demos/metadata.h - create mode 100644 qt4/demos/navigationtoolbar.cpp - create mode 100644 qt4/demos/navigationtoolbar.h - create mode 100644 qt4/demos/optcontent.cpp - create mode 100644 qt4/demos/optcontent.h - create mode 100644 qt4/demos/pageview.cpp - create mode 100644 qt4/demos/pageview.h - create mode 100644 qt4/demos/permissions.cpp - create mode 100644 qt4/demos/permissions.h - create mode 100644 qt4/demos/thumbnails.cpp - create mode 100644 qt4/demos/thumbnails.h - create mode 100644 qt4/demos/toc.cpp - create mode 100644 qt4/demos/toc.h - create mode 100644 qt4/demos/viewer.cpp - create mode 100644 qt4/demos/viewer.h - create mode 100644 qt4/src/.gitignore - create mode 100644 qt4/src/ArthurOutputDev.cc - create mode 100644 qt4/src/ArthurOutputDev.h - create mode 100644 qt4/src/CMakeLists.txt - create mode 100644 qt4/src/Doxyfile - create mode 100644 qt4/src/Mainpage.dox - create mode 100644 qt4/src/poppler-annotation-helper.h - create mode 100644 qt4/src/poppler-annotation-private.h - create mode 100644 qt4/src/poppler-annotation.cc - create mode 100644 qt4/src/poppler-annotation.h - create mode 100644 qt4/src/poppler-base-converter.cc - create mode 100644 qt4/src/poppler-converter-private.h - create mode 100644 qt4/src/poppler-document.cc - create mode 100644 qt4/src/poppler-embeddedfile-private.h - create mode 100644 qt4/src/poppler-embeddedfile.cc - create mode 100644 qt4/src/poppler-export.h - create mode 100644 qt4/src/poppler-fontinfo.cc - create mode 100644 qt4/src/poppler-form.cc - create mode 100644 qt4/src/poppler-form.h - create mode 100644 qt4/src/poppler-link-extractor-private.h - create mode 100644 qt4/src/poppler-link-extractor.cc - create mode 100644 qt4/src/poppler-link-private.h - create mode 100644 qt4/src/poppler-link.cc - create mode 100644 qt4/src/poppler-link.h - create mode 100644 qt4/src/poppler-media.cc - create mode 100644 qt4/src/poppler-media.h - create mode 100644 qt4/src/poppler-movie.cc - create mode 100644 qt4/src/poppler-optcontent-private.h - create mode 100644 qt4/src/poppler-optcontent.cc - create mode 100644 qt4/src/poppler-optcontent.h - create mode 100644 qt4/src/poppler-page-private.h - create mode 100644 qt4/src/poppler-page-transition-private.h - create mode 100644 qt4/src/poppler-page-transition.cc - create mode 100644 qt4/src/poppler-page-transition.h - create mode 100644 qt4/src/poppler-page.cc - create mode 100644 qt4/src/poppler-pdf-converter.cc - create mode 100644 qt4/src/poppler-private.cc - create mode 100644 qt4/src/poppler-private.h - create mode 100644 qt4/src/poppler-ps-converter.cc - create mode 100644 qt4/src/poppler-qiodeviceoutstream-private.h - create mode 100644 qt4/src/poppler-qiodeviceoutstream.cc - create mode 100644 qt4/src/poppler-qt4.h - create mode 100644 qt4/src/poppler-sound.cc - create mode 100644 qt4/src/poppler-textbox.cc - create mode 100644 qt4/tests/.gitignore - create mode 100644 qt4/tests/CMakeLists.txt - create mode 100644 qt4/tests/README.unittest - create mode 100644 qt4/tests/check_actualtext.cpp - create mode 100644 qt4/tests/check_attachments.cpp - create mode 100644 qt4/tests/check_dateConversion.cpp - create mode 100644 qt4/tests/check_fonts.cpp - create mode 100644 qt4/tests/check_goostring.cpp - create mode 100644 qt4/tests/check_lexer.cpp - create mode 100644 qt4/tests/check_links.cpp - create mode 100644 qt4/tests/check_metadata.cpp - create mode 100644 qt4/tests/check_optcontent.cpp - create mode 100644 qt4/tests/check_pagelabelinfo.cpp - create mode 100644 qt4/tests/check_pagelayout.cpp - create mode 100644 qt4/tests/check_pagemode.cpp - create mode 100644 qt4/tests/check_password.cpp - create mode 100644 qt4/tests/check_permissions.cpp - create mode 100644 qt4/tests/check_search.cpp - create mode 100644 qt4/tests/check_strings.cpp - create mode 100644 qt4/tests/poppler-attachments.cpp - create mode 100644 qt4/tests/poppler-fonts.cpp - create mode 100644 qt4/tests/poppler-forms.cpp - create mode 100644 qt4/tests/poppler-texts.cpp - create mode 100644 qt4/tests/stress-poppler-dir.cpp - create mode 100644 qt4/tests/stress-poppler-qt4.cpp - create mode 100644 qt4/tests/stress-threads-qt4.cpp - create mode 100644 qt4/tests/test-password-qt4.cpp - create mode 100644 qt4/tests/test-poppler-qt4.cpp - create mode 100644 qt4/tests/test-render-to-file.cpp - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 5e3d6a17..431059fb 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -40,6 +40,7 @@ set (CMAKE_CXX_EXTENSIONS OFF) - # command line switches - option(ENABLE_UNSTABLE_API_ABI_HEADERS "Install API/ABI unstable xpdf headers." OFF) - option(BUILD_GTK_TESTS "Whether to compile the GTK+ test programs." ON) -+option(BUILD_QT4_TESTS "Whether to compile the Qt4 test programs." ON) - option(BUILD_QT5_TESTS "Whether to compile the Qt5 test programs." ON) - option(BUILD_CPP_TESTS "Whether to compile the CPP test programs." ON) - option(ENABLE_SPLASH "Build the Splash graphics backend." ON) -@@ -47,6 +48,7 @@ option(ENABLE_UTILS "Compile poppler command line utils." ON) - option(ENABLE_GLIB "Compile poppler glib wrapper." ON) - option(ENABLE_GOBJECT_INTROSPECTION "Whether to generate GObject introspection." ON) - option(ENABLE_GTK_DOC "Whether to generate glib API documentation." OFF) -+option(ENABLE_QT4 "Compile poppler qt4 wrapper." ON) - option(ENABLE_QT5 "Compile poppler qt5 wrapper." ON) - set(ENABLE_LIBOPENJPEG "openjpeg2" CACHE STRING "Use libopenjpeg for JPX streams. Possible values: openjpeg2, unmaintained, none. 'unmaintained' gives you the internal unmaintained decoder. Use at your own risk. 'none' compiles no JPX decoder at all. Default: openjpeg2") - set(ENABLE_CMS "lcms2" CACHE STRING "Use color management system. Possible values: lcms2, none. 'none' disables color management system.") -@@ -112,6 +114,7 @@ set(OPI_SUPPORT ON) - set(TEXTOUT_WORD_LIST ON) - - # setting the minimum required versions for some components -+set(QT4_MIN_VERSION "4.7.0") - set(CAIRO_VERSION "1.10.0") - set(GLIB_REQUIRED "2.41") - -@@ -141,6 +144,13 @@ else() - message(FATAL_ERROR "Invalid ENABLE_DCTDECODER value.") - endif() - -+if (ENABLE_QT4) -+ macro_optional_find_package(Qt4) -+ if (NOT QT4_FOUND) -+ set(ENABLE_QT4 OFF) -+ endif() -+endif() -+ - if (ENABLE_QT5) - find_package(Qt5Core 5.5) # Update QT_DISABLE_DEPRECATED_BEFORE in qt5/CMakeLists.txt when increasing this - find_package(Qt5Gui) -@@ -661,6 +671,9 @@ if(ENABLE_GLIB) - add_subdirectory(glib) - endif() - add_subdirectory(test) -+if(ENABLE_QT4) -+ add_subdirectory(qt4) -+endif() - if(ENABLE_QT5) - add_subdirectory(qt5) - endif() -@@ -685,6 +698,9 @@ poppler_create_install_pkgconfig(poppler.pc ${CMAKE_INSTALL_LIBDIR}/pkgconfig) - if(ENABLE_SPLASH) - poppler_create_install_pkgconfig(poppler-splash.pc ${CMAKE_INSTALL_LIBDIR}/pkgconfig) - endif() -+ if(ENABLE_QT4) -+ poppler_create_install_pkgconfig(poppler-qt4.pc ${CMAKE_INSTALL_LIBDIR}/pkgconfig) -+ endif() - if(ENABLE_QT5) - poppler_create_install_pkgconfig(poppler-qt5.pc ${CMAKE_INSTALL_LIBDIR}/pkgconfig) - endif() -@@ -706,6 +722,7 @@ if(SPLASH_CMYK) - show_end_message("font configuration" ${font_configuration}) - show_end_message_yesno("splash output" ENABLE_SPLASH) - show_end_message_yesno("cairo output" CAIRO_FOUND) -+show_end_message_yesno("qt4 wrapper" ENABLE_QT4) - show_end_message_yesno("qt5 wrapper" ENABLE_QT5) - show_end_message_yesno("glib wrapper" ENABLE_GLIB) - show_end_message_yesno(" introspection" INTROSPECTION_FOUND) -diff --git a/cmake/modules/FindQt4.cmake b/cmake/modules/FindQt4.cmake -new file mode 100644 -index 00000000..79378b0c ---- /dev/null -+++ b/cmake/modules/FindQt4.cmake -@@ -0,0 +1,1311 @@ -+# - Find QT 4 -+# This module can be used to find Qt4. -+# The most important issue is that the Qt4 qmake is available via the system path. -+# This qmake is then used to detect basically everything else. -+# This module defines a number of key variables and macros. First is -+# QT_USE_FILE which is the path to a CMake file that can be included to compile -+# Qt 4 applications and libraries. By default, the QtCore and QtGui -+# libraries are loaded. This behavior can be changed by setting one or more -+# of the following variables to true: -+# QT_DONT_USE_QTCORE -+# QT_DONT_USE_QTGUI -+# QT_USE_QT3SUPPORT -+# QT_USE_QTASSISTANT -+# QT_USE_QTDESIGNER -+# QT_USE_QTMOTIF -+# QT_USE_QTMAIN -+# QT_USE_QTNETWORK -+# QT_USE_QTNSPLUGIN -+# QT_USE_QTOPENGL -+# QT_USE_QTSQL -+# QT_USE_QTXML -+# QT_USE_QTSVG -+# QT_USE_QTTEST -+# QT_USE_QTUITOOLS -+# QT_USE_QTDBUS -+# QT_USE_QTSCRIPT -+# -+# All the libraries required are stored in a variable called QT_LIBRARIES. -+# Add this variable to your TARGET_LINK_LIBRARIES. -+# -+# macro QT4_WRAP_CPP(outfiles inputfile ... OPTIONS ...) -+# create moc code from a list of files containing Qt class with -+# the Q_OBJECT declaration. Options may be given to moc, such as those found -+# when executing "moc -help" -+# -+# macro QT4_WRAP_UI(outfiles inputfile ... OPTIONS ...) -+# create code from a list of Qt designer ui files. -+# Options may be given to uic, such as those found -+# when executing "uic -help" -+# -+# macro QT4_ADD_RESOURCES(outfiles inputfile ... OPTIONS ...) -+# create code from a list of Qt resource files. -+# Options may be given to rcc, such as those found -+# when executing "rcc -help" -+# -+# macro QT4_AUTOMOC(inputfile ... ) -+# macro QT4_GENERATE_MOC(inputfile outputfile ) -+# -+# macro QT4_ADD_DBUS_INTERFACE(outfiles interface basename) -+# create a the interface header and implementation files with the -+# given basename from the given interface xml file and add it to -+# the list of sources. -+# To disable generating a namespace header, set the source file property -+# NO_NAMESPACE to TRUE on the interface file. -+# -+# macro QT4_ADD_DBUS_INTERFACES(outfiles inputfile ... ) -+# create the interface header and implementation files -+# for all listed interface xml files -+# the name will be automatically determined from the name of the xml file -+# To disable generating namespace headers, set the source file property -+# NO_NAMESPACE to TRUE for these inputfiles. -+# -+# macro QT4_ADD_DBUS_ADAPTOR(outfiles xmlfile parentheader parentclassname [basename] [classname]) -+# create a dbus adaptor (header and implementation file) from the xml file -+# describing the interface, and add it to the list of sources. The adaptor -+# forwards the calls to a parent class, defined in parentheader and named -+# parentclassname. The name of the generated files will be -+# adaptor.{cpp,h} where basename defaults to the basename of the xml file. -+# If is provided, then it will be used as the classname of the -+# adaptor itself. -+# -+# macro QT4_GENERATE_DBUS_INTERFACE( header [interfacename] OPTIONS ...) -+# generate the xml interface file from the given header. -+# If the optional argument interfacename is omitted, the name of the -+# interface file is constructed from the basename of the header with -+# the suffix .xml appended. -+# Options may be given to uic, such as those found when executing "qdbuscpp2xml --help" -+# -+# QT_FOUND If false, don't try to use Qt. -+# QT4_FOUND If false, don't try to use Qt 4. -+# -+# QT4_QTCORE_FOUND True if QtCore was found. -+# QT4_QTGUI_FOUND True if QtGui was found. -+# QT4_QT3SUPPORT_FOUND True if Qt3Support was found. -+# QT4_QTASSISTANT_FOUND True if QtAssistant was found. -+# QT4_QTDBUS_FOUND True if QtDBus was found. -+# QT4_QTDESIGNER_FOUND True if QtDesigner was found. -+# QT4_QTDESIGNERCOMPONENTS True if QtDesignerComponents was found. -+# QT4_QTMOTIF_FOUND True if QtMotif was found. -+# QT4_QTNETWORK_FOUND True if QtNetwork was found. -+# QT4_QTNSPLUGIN_FOUND True if QtNsPlugin was found. -+# QT4_QTOPENGL_FOUND True if QtOpenGL was found. -+# QT4_QTSQL_FOUND True if QtSql was found. -+# QT4_QTXML_FOUND True if QtXml was found. -+# QT4_QTSVG_FOUND True if QtSvg was found. -+# QT4_QTSCRIPT_FOUND True if QtScript was found. -+# QT4_QTTEST_FOUND True if QtTest was found. -+# QT4_QTUITOOLS_FOUND True if QtUiTools was found. -+# -+# QT4_DEFINITIONS Definitions to use when compiling code that uses Qt. -+# -+# QT4_INCLUDES List of paths to all include directories of -+# Qt4 QT4_INCLUDE_DIR and QT4_QTCORE_INCLUDE_DIR are -+# always in this variable even if NOTFOUND, -+# all other INCLUDE_DIRS are -+# only added if they are found. -+# -+# QT4_INCLUDE_DIR Path to "include" of Qt4 -+# QT4_QT4_INCLUDE_DIR Path to "include/Qt" -+# QT4_QT3SUPPORT_INCLUDE_DIR Path to "include/Qt3Support" -+# QT4_QTASSISTANT_INCLUDE_DIR Path to "include/QtAssistant" -+# QT4_QTCORE_INCLUDE_DIR Path to "include/QtCore" -+# QT4_QTDESIGNER_INCLUDE_DIR Path to "include/QtDesigner" -+# QT4_QTDESIGNERCOMPONENTS_INCLUDE_DIR Path to "include/QtDesigner" -+# QT4_QTDBUS_INCLUDE_DIR Path to "include/QtDBus" -+# QT4_QTGUI_INCLUDE_DIR Path to "include/QtGui" -+# QT4_QTMOTIF_INCLUDE_DIR Path to "include/QtMotif" -+# QT4_QTNETWORK_INCLUDE_DIR Path to "include/QtNetwork" -+# QT4_QTNSPLUGIN_INCLUDE_DIR Path to "include/QtNsPlugin" -+# QT4_QTOPENGL_INCLUDE_DIR Path to "include/QtOpenGL" -+# QT4_QTSQL_INCLUDE_DIR Path to "include/QtSql" -+# QT4_QTXML_INCLUDE_DIR Path to "include/QtXml" -+# QT4_QTSVG_INCLUDE_DIR Path to "include/QtSvg" -+# QT4_QTSCRIPT_INCLUDE_DIR Path to "include/QtScript" -+# QT4_QTTEST_INCLUDE_DIR Path to "include/QtTest" -+# -+# QT4_LIBRARY_DIR Path to "lib" of Qt4 -+# -+# QT4_PLUGINS_DIR Path to "plugins" for Qt4 -+# -+# For every library of Qt, a QT4_QTFOO_LIBRARY variable is defined, with the full path to the library. -+# -+# So there are the following variables: -+# The Qt3Support library: QT4_QT3SUPPORT_LIBRARY -+# -+# The QtAssistant library: QT4_QTASSISTANT_LIBRARY -+# -+# The QtCore library: QT4_QTCORE_LIBRARY -+# -+# The QtDBus library: QT4_QTDBUS_LIBRARY -+# -+# The QtDesigner library: QT4_QTDESIGNER_LIBRARY -+# -+# The QtDesignerComponents library: QT4_QTDESIGNERCOMPONENTS_LIBRARY -+# -+# The QtGui library: QT4_QTGUI_LIBRARY -+# -+# The QtMotif library: QT4_QTMOTIF_LIBRARY -+# -+# The QtNetwork library: QT4_QTNETWORK_LIBRARY -+# -+# The QtNsPLugin library: QT4_QTNSPLUGIN_LIBRARY -+# -+# The QtOpenGL library: QT4_QTOPENGL_LIBRARY -+# -+# The QtSql library: QT4_QTSQL_LIBRARY -+# -+# The QtXml library: QT4_QTXML_LIBRARY -+# -+# The QtSvg library: QT4_QTSVG_LIBRARY -+# -+# The QtScript library: QT4_QTSCRIPT_LIBRARY -+# -+# The QtTest library: QT4_QTTEST_LIBRARY -+# -+# The qtmain library for Windows QT4_QTMAIN_LIBRARY -+# -+# The QtUiTools library: QT4_QTUITOOLS_LIBRARY -+# -+# also defined, but NOT for general use are -+# QT4_MOC_EXECUTABLE Where to find the moc tool. -+# QT4_UIC_EXECUTABLE Where to find the uic tool. -+# QT_UIC3_EXECUTABLE Where to find the uic3 tool. -+# QT_RCC_EXECUTABLE Where to find the rcc tool -+# QT_DBUSCPP2XML_EXECUTABLE Where to find the qdbuscpp2xml tool. -+# QT_DBUSXML2CPP_EXECUTABLE Where to find the qdbusxml2cpp tool. -+# -+# QT_DOC_DIR Path to "doc" of Qt4 -+# QT_MKSPECS_DIR Path to "mkspecs" of Qt4 -+# -+# -+# These are around for backwards compatibility -+# they will be set -+# QT_WRAP_CPP Set true if QT4_MOC_EXECUTABLE is found -+# QT_WRAP_UI Set true if QT4_UIC_EXECUTABLE is found -+# -+# These variables do _NOT_ have any effect anymore (compared to FindQt.cmake) -+# QT_MT_REQUIRED Qt4 is now always multithreaded -+# -+# These variables are set to "" Because Qt structure changed -+# (They make no sense in Qt4) -+# QT4_QT_LIBRARY Qt-Library is now split -+ -+# Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. -+# See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. -+ -+if (QT4_QMAKE_FOUND) -+ # Check already done in this cmake run, nothing more to do -+ -+else (QT4_QMAKE_FOUND) -+ -+# check that QT_NO_DEBUG is defined for release configurations -+MACRO(QT_CHECK_FLAG_EXISTS FLAG VAR DOC) -+ IF(NOT ${VAR} MATCHES "${FLAG}") -+ SET(${VAR} "${${VAR}} ${FLAG}" -+ CACHE STRING "Flags used by the compiler during ${DOC} builds." FORCE) -+ ENDIF(NOT ${VAR} MATCHES "${FLAG}") -+ENDMACRO(QT_CHECK_FLAG_EXISTS FLAG VAR) -+QT_CHECK_FLAG_EXISTS(-DQT_NO_DEBUG CMAKE_CXX_FLAGS_RELWITHDEBINFO "Release with Debug Info") -+QT_CHECK_FLAG_EXISTS(-DQT_NO_DEBUG CMAKE_CXX_FLAGS_RELEASE "release") -+QT_CHECK_FLAG_EXISTS(-DQT_NO_DEBUG CMAKE_CXX_FLAGS_MINSIZEREL "release minsize") -+ -+INCLUDE(CheckSymbolExists) -+INCLUDE(MacroAddFileDependencies) -+INCLUDE(MacroPushRequiredVars) -+ -+SET(QT_USE_FILE ${CMAKE_ROOT}/Modules/UseQt4.cmake) -+ -+SET( QT4_DEFINITIONS "") -+ -+IF (WIN32) -+ SET(QT4_DEFINITIONS -DQT_DLL) -+ENDIF(WIN32) -+ -+SET(QT4_INSTALLED_VERSION_TOO_OLD FALSE) -+ -+# macro for asking qmake to process pro files -+MACRO(QT_QUERY_QMAKE outvar invar) -+ FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmpQmake/tmp.pro -+ "message(CMAKE_MESSAGE<$$${invar}>)") -+ -+ # Invoke qmake with the tmp.pro program to get the desired -+ # information. Use the same variable for both stdout and stderr -+ # to make sure we get the output on all platforms. -+ EXECUTE_PROCESS(COMMAND ${QT_QMAKE_EXECUTABLE} -+ WORKING_DIRECTORY -+ ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmpQmake -+ OUTPUT_VARIABLE _qmake_query_output -+ RESULT_VARIABLE _qmake_result -+ ERROR_VARIABLE _qmake_query_output ) -+ -+ FILE(REMOVE_RECURSE -+ "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmpQmake") -+ -+ IF(_qmake_result) -+ MESSAGE(WARNING " querying qmake for ${invar}. qmake reported:\n${_qmake_query_output}") -+ ELSE(_qmake_result) -+ STRING(REGEX REPLACE ".*CMAKE_MESSAGE<([^>]*).*" "\\1" ${outvar} "${_qmake_query_output}") -+ ENDIF(_qmake_result) -+ -+ENDMACRO(QT_QUERY_QMAKE) -+ -+MACRO(VERIFY_QMAKE_QT4) -+ EXEC_PROGRAM(${QT_QMAKE_EXECUTABLE} ARGS "-query QT_VERSION" OUTPUT_VARIABLE QTVERSION) -+ -+ # check for qt3 qmake and then try and find qmake4 or qmake-qt4 in the path -+ IF("${QTVERSION}" MATCHES "Unknown") -+ SET(QT_QMAKE_EXECUTABLE NOTFOUND CACHE FILEPATH "" FORCE) -+ FIND_PROGRAM(QT_QMAKE_EXECUTABLE NAMES qmake4 qmake-qt4 PATHS -+ "[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\4.0.0;InstallDir]/bin" -+ "[HKEY_CURRENT_USER\\Software\\Trolltech\\Versions\\4.0.0;InstallDir]/bin" -+ $ENV{QTDIR}/bin -+ ) -+ IF(QT_QMAKE_EXECUTABLE) -+ EXEC_PROGRAM(${QT_QMAKE_EXECUTABLE} -+ ARGS "-query QT_VERSION" OUTPUT_VARIABLE QTVERSION) -+ ENDIF(QT_QMAKE_EXECUTABLE) -+ ENDIF("${QTVERSION}" MATCHES "Unknown") -+ -+ # check that we found the Qt4 qmake, Qt3 qmake output won't match here -+ STRING(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" qt_version_tmp "${QTVERSION}") -+ IF (qt_version_tmp) -+ -+ # we need at least version 4.0.0 -+ IF (NOT QT4_MIN_VERSION) -+ SET(QT4_MIN_VERSION "4.0.0") -+ ENDIF (NOT QT4_MIN_VERSION) -+ -+ #now parse the parts of the user given version string into variables -+ STRING(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" req_qt_major_vers "${QT4_MIN_VERSION}") -+ IF (NOT req_qt_major_vers) -+ MESSAGE( FATAL_ERROR "Invalid Qt version string given: \"${QT4_MIN_VERSION}\", expected e.g. \"4.0.1\"") -+ ENDIF (NOT req_qt_major_vers) -+ -+ # now parse the parts of the user given version string into variables -+ STRING(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" req_qt_major_vers "${QT4_MIN_VERSION}") -+ STRING(REGEX REPLACE "^[0-9]+\\.([0-9])+\\.[0-9]+" "\\1" req_qt_minor_vers "${QT4_MIN_VERSION}") -+ STRING(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" req_qt_patch_vers "${QT4_MIN_VERSION}") -+ -+ IF (NOT req_qt_major_vers EQUAL 4) -+ MESSAGE( FATAL_ERROR "Invalid Qt version string given: \"${QT4_MIN_VERSION}\", major version 4 is required, e.g. \"4.0.1\"") -+ ENDIF (NOT req_qt_major_vers EQUAL 4) -+ -+ # and now the version string given by qmake -+ STRING(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" found_qt_major_vers "${QTVERSION}") -+ STRING(REGEX REPLACE "^[0-9]+\\.([0-9])+\\.[0-9]+.*" "\\1" found_qt_minor_vers "${QTVERSION}") -+ STRING(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" found_qt_patch_vers "${QTVERSION}") -+ IF (${found_qt_major_vers} EQUAL 4) -+ # compute an overall version number which can be compared at once -+ MATH(EXPR req_vers "${req_qt_major_vers}*10000 + ${req_qt_minor_vers}*100 + ${req_qt_patch_vers}") -+ MATH(EXPR found_vers "${found_qt_major_vers}*10000 + ${found_qt_minor_vers}*100 + ${found_qt_patch_vers}") -+ -+ -+ IF (found_vers LESS req_vers) -+ SET(QT4_QMAKE_FOUND FALSE) -+ SET(QT4_INSTALLED_VERSION_TOO_OLD TRUE) -+ ELSE (found_vers LESS req_vers) -+ SET(QT4_QMAKE_FOUND TRUE) -+ ENDIF (found_vers LESS req_vers) -+ ENDIF () -+ ENDIF (qt_version_tmp) -+ENDMACRO() -+ -+GET_FILENAME_COMPONENT(qt_install_version "[HKEY_CURRENT_USER\\Software\\trolltech\\Versions;DefaultQtVersion]" NAME) -+# check for qmake -+FIND_PROGRAM(QT_QMAKE_EXECUTABLE NAMES qmake qmake4 qmake-qt4 PATHS -+ "[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\4.0.0;InstallDir]/bin" -+ "[HKEY_CURRENT_USER\\Software\\Trolltech\\Versions\\4.0.0;InstallDir]/bin" -+ "[HKEY_CURRENT_USER\\Software\\Trolltech\\Versions\\${qt_install_version};InstallDir]/bin" -+ $ENV{QTDIR}/bin -+) -+ -+IF (QT_QMAKE_EXECUTABLE) -+ -+ SET(QT4_QMAKE_FOUND FALSE) -+ VERIFY_QMAKE_QT4() -+ -+ IF (NOT QT4_QMAKE_FOUND) -+ FIND_PROGRAM(QT_QMAKE_EXECUTABLE2 NAMES qmake4 qmake-qt4 PATHS -+ "[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\4.0.0;InstallDir]/bin" -+ "[HKEY_CURRENT_USER\\Software\\Trolltech\\Versions\\4.0.0;InstallDir]/bin" -+ "[HKEY_CURRENT_USER\\Software\\Trolltech\\Versions\\${qt_install_version};InstallDir]/bin" -+ $ENV{QTDIR}/bin -+ ) -+ SET(QT_QMAKE_EXECUTABLE ${QT_QMAKE_EXECUTABLE2}) -+ VERIFY_QMAKE_QT4() -+ ENDIF() -+ -+ENDIF (QT_QMAKE_EXECUTABLE) -+ -+IF (QT4_QMAKE_FOUND) -+ -+ if (WIN32) -+ # get qt install dir -+ get_filename_component(_DIR ${QT_QMAKE_EXECUTABLE} PATH ) -+ get_filename_component(QT_INSTALL_DIR ${_DIR} PATH ) -+ endif (WIN32) -+ -+ # ask qmake for the library dir -+ # Set QT4_LIBRARY_DIR -+ IF (NOT QT4_LIBRARY_DIR) -+ EXEC_PROGRAM( ${QT_QMAKE_EXECUTABLE} -+ ARGS "-query QT_INSTALL_LIBS" -+ OUTPUT_VARIABLE QT4_LIBRARY_DIR_TMP ) -+ IF(EXISTS "${QT4_LIBRARY_DIR_TMP}") -+ SET(QT4_LIBRARY_DIR ${QT4_LIBRARY_DIR_TMP} CACHE PATH "Qt library dir") -+ ELSE(EXISTS "${QT4_LIBRARY_DIR_TMP}") -+ MESSAGE("Warning: QT_QMAKE_EXECUTABLE reported QT_INSTALL_LIBS as ${QT4_LIBRARY_DIR_TMP}") -+ MESSAGE("Warning: ${QT4_LIBRARY_DIR_TMP} does NOT exist, Qt must NOT be installed correctly.") -+ ENDIF(EXISTS "${QT4_LIBRARY_DIR_TMP}") -+ ENDIF(NOT QT4_LIBRARY_DIR) -+ -+ IF (APPLE) -+ IF (EXISTS ${QT4_LIBRARY_DIR}/QtCore.framework) -+ SET(QT_USE_FRAMEWORKS ON -+ CACHE BOOL "Set to ON if Qt build uses frameworks.") -+ ELSE (EXISTS ${QT4_LIBRARY_DIR}/QtCore.framework) -+ SET(QT_USE_FRAMEWORKS OFF -+ CACHE BOOL "Set to ON if Qt build uses frameworks.") -+ ENDIF (EXISTS ${QT4_LIBRARY_DIR}/QtCore.framework) -+ -+ MARK_AS_ADVANCED(QT_USE_FRAMEWORKS) -+ ENDIF (APPLE) -+ -+ # ask qmake for the binary dir -+ IF (NOT QT_BINARY_DIR) -+ EXEC_PROGRAM(${QT_QMAKE_EXECUTABLE} -+ ARGS "-query QT_INSTALL_BINS" -+ OUTPUT_VARIABLE qt_bins ) -+ SET(QT_BINARY_DIR ${qt_bins} CACHE INTERNAL "") -+ ENDIF (NOT QT_BINARY_DIR) -+ -+ # ask qmake for the include dir -+ IF (NOT QT_HEADERS_DIR) -+ EXEC_PROGRAM( ${QT_QMAKE_EXECUTABLE} -+ ARGS "-query QT_INSTALL_HEADERS" -+ OUTPUT_VARIABLE qt_headers ) -+ SET(QT_HEADERS_DIR ${qt_headers} CACHE INTERNAL "") -+ ENDIF(NOT QT_HEADERS_DIR) -+ -+ -+ # ask qmake for the documentation directory -+ IF (NOT QT_DOC_DIR) -+ EXEC_PROGRAM( ${QT_QMAKE_EXECUTABLE} -+ ARGS "-query QT_INSTALL_DOCS" -+ OUTPUT_VARIABLE qt_doc_dir ) -+ SET(QT_DOC_DIR ${qt_doc_dir} CACHE PATH "The location of the Qt docs") -+ ENDIF (NOT QT_DOC_DIR) -+ -+ # ask qmake for the mkspecs directory -+ IF (NOT QT_MKSPECS_DIR) -+ EXEC_PROGRAM( ${QT_QMAKE_EXECUTABLE} -+ ARGS "-query QMAKE_MKSPECS" -+ OUTPUT_VARIABLE qt_mkspecs_dirs ) -+ STRING(REPLACE ":" ";" qt_mkspecs_dirs "${qt_mkspecs_dirs}") -+ FIND_PATH(QT_MKSPECS_DIR qconfig.pri PATHS ${qt_mkspecs_dirs} -+ DOC "The location of the Qt mkspecs containing qconfig.pri" -+ NO_DEFAULT_PATH ) -+ ENDIF (NOT QT_MKSPECS_DIR) -+ -+ # ask qmake for the plugins directory -+ IF (NOT QT4_PLUGINS_DIR) -+ EXEC_PROGRAM( ${QT_QMAKE_EXECUTABLE} -+ ARGS "-query QT_INSTALL_PLUGINS" -+ OUTPUT_VARIABLE qt_plugins_dir ) -+ SET(QT4_PLUGINS_DIR ${qt_plugins_dir} CACHE PATH "The location of the Qt plugins") -+ ENDIF (NOT QT4_PLUGINS_DIR) -+ ######################################## -+ # -+ # Setting the INCLUDE-Variables -+ # -+ ######################################## -+ -+ FIND_PATH(QT4_QTCORE_INCLUDE_DIR QtGlobal -+ ${QT_HEADERS_DIR}/QtCore -+ ${QT4_LIBRARY_DIR}/QtCore.framework/Headers -+ NO_DEFAULT_PATH -+ ) -+ -+ # Set QT4_INCLUDE_DIR by removine "/QtCore" in the string ${QT4_QTCORE_INCLUDE_DIR} -+ IF( QT4_QTCORE_INCLUDE_DIR AND NOT QT4_INCLUDE_DIR) -+ IF (QT_USE_FRAMEWORKS) -+ SET(QT4_INCLUDE_DIR ${QT_HEADERS_DIR}) -+ ELSE (QT_USE_FRAMEWORKS) -+ STRING( REGEX REPLACE "/QtCore$" "" qt4_include_dir ${QT4_QTCORE_INCLUDE_DIR}) -+ SET( QT4_INCLUDE_DIR ${qt4_include_dir} CACHE PATH "") -+ ENDIF (QT_USE_FRAMEWORKS) -+ ENDIF( QT4_QTCORE_INCLUDE_DIR AND NOT QT4_INCLUDE_DIR) -+ -+ IF( NOT QT4_INCLUDE_DIR) -+ IF( NOT Qt4_FIND_QUIETLY AND Qt4_FIND_REQUIRED) -+ MESSAGE( FATAL_ERROR "Could NOT find QtGlobal header") -+ ENDIF( NOT Qt4_FIND_QUIETLY AND Qt4_FIND_REQUIRED) -+ ENDIF( NOT QT4_INCLUDE_DIR) -+ -+ ############################################# -+ # -+ # Find out what window system we're using -+ # -+ ############################################# -+ # Save required includes and required_flags variables -+ macro_push_required_vars() -+ # Add QT4_INCLUDE_DIR to CMAKE_REQUIRED_INCLUDES -+ SET(CMAKE_REQUIRED_INCLUDES "${CMAKE_REQUIRED_INCLUDES};${QT4_INCLUDE_DIR}") -+ # On Mac OS X when Qt has framework support, also add the framework path -+ IF( QT_USE_FRAMEWORKS ) -+ SET(CMAKE_REQUIRED_FLAGS "-F${QT4_LIBRARY_DIR} ") -+ ENDIF( QT_USE_FRAMEWORKS ) -+ # Check for Window system symbols (note: only one should end up being set) -+ CHECK_SYMBOL_EXISTS(Q_WS_X11 "QtCore/qglobal.h" Q_WS_X11) -+ CHECK_SYMBOL_EXISTS(Q_WS_WIN "QtCore/qglobal.h" Q_WS_WIN) -+ CHECK_SYMBOL_EXISTS(Q_WS_QWS "QtCore/qglobal.h" Q_WS_QWS) -+ CHECK_SYMBOL_EXISTS(Q_WS_MAC "QtCore/qglobal.h" Q_WS_MAC) -+ -+ IF (QT4_QTCOPY_REQUIRED) -+ CHECK_SYMBOL_EXISTS(QT_IS_QTCOPY "QtCore/qglobal.h" QT_KDE_QT_COPY) -+ IF (NOT QT_IS_QTCOPY) -+ MESSAGE(FATAL_ERROR "qt-copy is required, but hasn't been found") -+ ENDIF (NOT QT_IS_QTCOPY) -+ ENDIF (QT4_QTCOPY_REQUIRED) -+ -+ # Restore CMAKE_REQUIRED_INCLUDES+CMAKE_REQUIRED_FLAGS variables -+ macro_pop_required_vars() -+ # -+ ############################################# -+ -+ IF (QT_USE_FRAMEWORKS) -+ SET(QT4_DEFINITIONS ${QT4_DEFINITIONS} -F${QT4_LIBRARY_DIR} -L${QT4_LIBRARY_DIR} ) -+ ENDIF (QT_USE_FRAMEWORKS) -+ -+ # Set QT4_QT3SUPPORT_INCLUDE_DIR -+ FIND_PATH(QT4_QT3SUPPORT_INCLUDE_DIR Qt3Support -+ PATHS -+ ${QT4_INCLUDE_DIR}/Qt3Support -+ ${QT4_LIBRARY_DIR}/Qt3Support.framework/Headers -+ NO_DEFAULT_PATH -+ ) -+ -+ # Set QT4_QT4_INCLUDE_DIR -+ FIND_PATH(QT4_QT4_INCLUDE_DIR qglobal.h -+ PATHS -+ ${QT4_INCLUDE_DIR}/Qt -+ ${QT4_LIBRARY_DIR}/QtCore.framework/Headers -+ NO_DEFAULT_PATH -+ ) -+ -+ # Set QT4_QTGUI_INCLUDE_DIR -+ FIND_PATH(QT4_QTGUI_INCLUDE_DIR QtGui -+ PATHS -+ ${QT4_INCLUDE_DIR}/QtGui -+ ${QT4_LIBRARY_DIR}/QtGui.framework/Headers -+ NO_DEFAULT_PATH -+ ) -+ -+ # Set QT4_QTSVG_INCLUDE_DIR -+ FIND_PATH(QT4_QTSVG_INCLUDE_DIR QtSvg -+ PATHS -+ ${QT4_INCLUDE_DIR}/QtSvg -+ ${QT4_LIBRARY_DIR}/QtSvg.framework/Headers -+ NO_DEFAULT_PATH -+ ) -+ -+ # Set QT4_QTSCRIPT_INCLUDE_DIR -+ FIND_PATH(QT4_QTSCRIPT_INCLUDE_DIR QtScript -+ PATHS -+ ${QT4_INCLUDE_DIR}/QtScript -+ ${QT4_LIBRARY_DIR}/QtScript.framework/Headers -+ NO_DEFAULT_PATH -+ ) -+ -+ # Set QT4_QTTEST_INCLUDE_DIR -+ FIND_PATH(QT4_QTTEST_INCLUDE_DIR QtTest -+ PATHS -+ ${QT4_INCLUDE_DIR}/QtTest -+ ${QT4_LIBRARY_DIR}/QtTest.framework/Headers -+ NO_DEFAULT_PATH -+ ) -+ -+ # Set QT4_QTUITOOLS_INCLUDE_DIR -+ FIND_PATH(QT4_QTUITOOLS_INCLUDE_DIR QtUiTools -+ PATHS -+ ${QT4_INCLUDE_DIR}/QtUiTools -+ ${QT4_LIBRARY_DIR}/QtUiTools.framework/Headers -+ NO_DEFAULT_PATH -+ ) -+ -+ -+ -+ # Set QT4_QTMOTIF_INCLUDE_DIR -+ IF(Q_WS_X11) -+ FIND_PATH(QT4_QTMOTIF_INCLUDE_DIR QtMotif PATHS ${QT4_INCLUDE_DIR}/QtMotif NO_DEFAULT_PATH ) -+ ENDIF(Q_WS_X11) -+ -+ # Set QT4_QTNETWORK_INCLUDE_DIR -+ FIND_PATH(QT4_QTNETWORK_INCLUDE_DIR QtNetwork -+ PATHS -+ ${QT4_INCLUDE_DIR}/QtNetwork -+ ${QT4_LIBRARY_DIR}/QtNetwork.framework/Headers -+ NO_DEFAULT_PATH -+ ) -+ -+ # Set QT4_QTNSPLUGIN_INCLUDE_DIR -+ FIND_PATH(QT4_QTNSPLUGIN_INCLUDE_DIR QtNsPlugin -+ PATHS -+ ${QT4_INCLUDE_DIR}/QtNsPlugin -+ ${QT4_LIBRARY_DIR}/QtNsPlugin.framework/Headers -+ NO_DEFAULT_PATH -+ ) -+ -+ # Set QT4_QTOPENGL_INCLUDE_DIR -+ FIND_PATH(QT4_QTOPENGL_INCLUDE_DIR QtOpenGL -+ PATHS -+ ${QT4_INCLUDE_DIR}/QtOpenGL -+ ${QT4_LIBRARY_DIR}/QtOpenGL.framework/Headers -+ NO_DEFAULT_PATH -+ ) -+ -+ # Set QT4_QTSQL_INCLUDE_DIR -+ FIND_PATH(QT4_QTSQL_INCLUDE_DIR QtSql -+ PATHS -+ ${QT4_INCLUDE_DIR}/QtSql -+ ${QT4_LIBRARY_DIR}/QtSql.framework/Headers -+ NO_DEFAULT_PATH -+ ) -+ -+ # Set QT4_QTXML_INCLUDE_DIR -+ FIND_PATH(QT4_QTXML_INCLUDE_DIR QtXml -+ PATHS -+ ${QT4_INCLUDE_DIR}/QtXml -+ ${QT4_LIBRARY_DIR}/QtXml.framework/Headers -+ NO_DEFAULT_PATH -+ ) -+ -+ # Set QT4_QTASSISTANT_INCLUDE_DIR -+ FIND_PATH(QT4_QTASSISTANT_INCLUDE_DIR QtAssistant -+ PATHS -+ ${QT4_INCLUDE_DIR}/QtAssistant -+ ${QT_HEADERS_DIR}/QtAssistant -+ ${QT4_LIBRARY_DIR}/QtAssistant.framework/Headers -+ NO_DEFAULT_PATH -+ ) -+ -+ # Set QT4_QTDESIGNER_INCLUDE_DIR -+ FIND_PATH(QT4_QTDESIGNER_INCLUDE_DIR QDesignerComponents -+ PATHS -+ ${QT4_INCLUDE_DIR}/QtDesigner -+ ${QT_HEADERS_DIR}/QtDesigner -+ ${QT4_LIBRARY_DIR}/QtDesigner.framework/Headers -+ NO_DEFAULT_PATH -+ ) -+ -+ # Set QT4_QTDESIGNERCOMPONENTS_INCLUDE_DIR -+ FIND_PATH(QT4_QTDESIGNERCOMPONENTS_INCLUDE_DIR QDesignerComponents -+ PATHS -+ ${QT4_INCLUDE_DIR}/QtDesigner -+ ${QT_HEADERS_DIR}/QtDesigner -+ NO_DEFAULT_PATH -+ ) -+ -+ -+ # Set QT4_QTDBUS_INCLUDE_DIR -+ FIND_PATH(QT4_QTDBUS_INCLUDE_DIR QtDBus -+ PATHS -+ ${QT4_INCLUDE_DIR}/QtDBus -+ ${QT_HEADERS_DIR}/QtDBus -+ NO_DEFAULT_PATH -+ ) -+ -+ # Make variables changeble to the advanced user -+ MARK_AS_ADVANCED( QT4_LIBRARY_DIR QT4_INCLUDE_DIR QT4_QT4_INCLUDE_DIR QT_DOC_DIR QT_MKSPECS_DIR QT4_PLUGINS_DIR) -+ -+ # Set QT4_INCLUDES -+ SET( QT4_INCLUDES ${QT4_QT4_INCLUDE_DIR} ${QT_MKSPECS_DIR}/default ${QT4_INCLUDE_DIR}) -+ -+ -+ ######################################## -+ # -+ # Setting the LIBRARY-Variables -+ # -+ ######################################## -+ -+ IF (QT_USE_FRAMEWORKS) -+ # If FIND_LIBRARY found libraries in Apple frameworks, we would NOT have -+ # to jump through these hoops. -+ IF(EXISTS ${QT4_LIBRARY_DIR}/QtCore.framework) -+ SET(QT4_QTCORE_FOUND TRUE) -+ SET(QT4_QTCORE_LIBRARY "-F${QT4_LIBRARY_DIR} -framework QtCore" CACHE STRING "The QtCore library.") -+ ELSE(EXISTS ${QT4_LIBRARY_DIR}/QtCore.framework) -+ SET(QT4_QTCORE_FOUND FALSE) -+ ENDIF(EXISTS ${QT4_LIBRARY_DIR}/QtCore.framework) -+ -+ IF(EXISTS ${QT4_LIBRARY_DIR}/QtGui.framework) -+ SET(QT4_QTGUI_FOUND TRUE) -+ SET(QT4_QTGUI_LIBRARY "-F${QT4_LIBRARY_DIR} -framework QtGui" CACHE STRING "The QtGui library.") -+ ELSE(EXISTS ${QT4_LIBRARY_DIR}/QtGui.framework) -+ SET(QT4_QTGUI_FOUND FALSE) -+ ENDIF(EXISTS ${QT4_LIBRARY_DIR}/QtGui.framework) -+ -+ IF(EXISTS ${QT4_LIBRARY_DIR}/Qt3Support.framework) -+ SET(QT4_QT3SUPPORT_FOUND TRUE) -+ SET(QT4_QT3SUPPORT_LIBRARY "-F${QT4_LIBRARY_DIR} -framework Qt3Support" CACHE STRING "The Qt3Support library.") -+ ELSE(EXISTS ${QT4_LIBRARY_DIR}/Qt3Support.framework) -+ SET(QT4_QT3SUPPORT_FOUND FALSE) -+ ENDIF(EXISTS ${QT4_LIBRARY_DIR}/Qt3Support.framework) -+ -+ IF(EXISTS ${QT4_LIBRARY_DIR}/QtNetwork.framework) -+ SET(QT4_QTNETWORK_FOUND TRUE) -+ SET(QT4_QTNETWORK_LIBRARY "-F${QT4_LIBRARY_DIR} -framework QtNetwork" CACHE STRING "The QtNetwork library.") -+ ELSE(EXISTS ${QT4_LIBRARY_DIR}/QtNetwork.framework) -+ SET(QT4_QTNETWORK_FOUND FALSE) -+ ENDIF(EXISTS ${QT4_LIBRARY_DIR}/QtNetwork.framework) -+ -+ IF(EXISTS ${QT4_LIBRARY_DIR}/QtOpenGL.framework) -+ SET(QT4_QTOPENGL_FOUND TRUE) -+ SET(QT4_QTOPENGL_LIBRARY "-F${QT4_LIBRARY_DIR} -framework QtOpenGL" CACHE STRING "The QtOpenGL library.") -+ ELSE(EXISTS ${QT4_LIBRARY_DIR}/QtOpenGL.framework) -+ SET(QT4_QTOPENGL_FOUND FALSE) -+ ENDIF(EXISTS ${QT4_LIBRARY_DIR}/QtOpenGL.framework) -+ -+ IF(EXISTS ${QT4_LIBRARY_DIR}/QtSql.framework) -+ SET(QT4_QTSQL_FOUND TRUE) -+ SET(QT4_QTSQL_LIBRARY "-F${QT4_LIBRARY_DIR} -framework QtSql" CACHE STRING "The QtSql library.") -+ ELSE(EXISTS ${QT4_LIBRARY_DIR}/QtSql.framework) -+ SET(QT4_QTSQL_FOUND FALSE) -+ ENDIF(EXISTS ${QT4_LIBRARY_DIR}/QtSql.framework) -+ -+ IF(EXISTS ${QT4_LIBRARY_DIR}/QtXml.framework) -+ SET(QT4_QTXML_FOUND TRUE) -+ SET(QT4_QTXML_LIBRARY "-F${QT4_LIBRARY_DIR} -framework QtXml" CACHE STRING "The QtXml library.") -+ ELSE(EXISTS ${QT4_LIBRARY_DIR}/QtXml.framework) -+ SET(QT4_QTXML_FOUND FALSE) -+ ENDIF(EXISTS ${QT4_LIBRARY_DIR}/QtXml.framework) -+ -+ IF(EXISTS ${QT4_LIBRARY_DIR}/QtSvg.framework) -+ SET(QT4_QTSVG_FOUND TRUE) -+ SET(QT4_QTSVG_LIBRARY "-F${QT4_LIBRARY_DIR} -framework QtSvg" CACHE STRING "The QtSvg library.") -+ ELSE(EXISTS ${QT4_LIBRARY_DIR}/QtSvg.framework) -+ SET(QT4_QTSVG_FOUND FALSE) -+ ENDIF(EXISTS ${QT4_LIBRARY_DIR}/QtSvg.framework) -+ -+ IF(EXISTS ${QT4_LIBRARY_DIR}/QtDBus.framework) -+ SET(QT4_QTDBUS_FOUND TRUE) -+ SET(QT4_QTDBUS_LIBRARY "-F${QT4_LIBRARY_DIR} -framework QtDBus" CACHE STRING "The QtDBus library.") -+ ELSE(EXISTS ${QT4_LIBRARY_DIR}/QtDBus.framework) -+ SET(QT4_QTDBUS_FOUND FALSE) -+ ENDIF(EXISTS ${QT4_LIBRARY_DIR}/QtDBus.framework) -+ -+ IF(EXISTS ${QT4_LIBRARY_DIR}/QtTest.framework) -+ SET(QT4_QTTEST_FOUND TRUE) -+ SET(QT4_QTTEST_LIBRARY "-F${QT4_LIBRARY_DIR} -framework QtTest" CACHE STRING "The QtTest library.") -+ ELSE(EXISTS ${QT4_LIBRARY_DIR}/QtTest.framework) -+ SET(QT4_QTTEST_FOUND FALSE) -+ ENDIF(EXISTS ${QT4_LIBRARY_DIR}/QtTest.framework) -+ -+ # WTF? why don't we have frameworks? :P -+ # Set QT4_QTUITOOLS_LIBRARY -+ FIND_LIBRARY(QT4_QTUITOOLS_LIBRARY NAMES QtUiTools QtUiTools4 PATHS ${QT4_LIBRARY_DIR} ) -+ # Set QT4_QTSCRIPT_LIBRARY -+ FIND_LIBRARY(QT4_QTSCRIPT_LIBRARY NAMES QtScript QtScript4 PATHS ${QT4_LIBRARY_DIR} ) -+ -+ ELSE (QT_USE_FRAMEWORKS) -+ -+ # Set QT4_QTCORE_LIBRARY by searching for a lib with "QtCore." as part of the filename -+ FIND_LIBRARY(QT4_QTCORE_LIBRARY NAMES QtCore QtCore4 QtCored4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH ) -+ -+ # Set QT4_QT3SUPPORT_LIBRARY -+ FIND_LIBRARY(QT4_QT3SUPPORT_LIBRARY NAMES Qt3Support Qt3Support4 Qt3Supportd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ -+ # Set QT4_QTGUI_LIBRARY -+ FIND_LIBRARY(QT4_QTGUI_LIBRARY NAMES QtGui QtGui4 QtGuid4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ -+ # Set QT4_QTMOTIF_LIBRARY -+ IF(Q_WS_X11) -+ FIND_LIBRARY(QT4_QTMOTIF_LIBRARY NAMES QtMotif PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ ENDIF(Q_WS_X11) -+ -+ # Set QT4_QTNETWORK_LIBRARY -+ FIND_LIBRARY(QT4_QTNETWORK_LIBRARY NAMES QtNetwork QtNetwork4 QtNetworkd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ -+ # Set QT4_QTNSPLUGIN_LIBRARY -+ FIND_LIBRARY(QT4_QTNSPLUGIN_LIBRARY NAMES QtNsPlugin PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ -+ # Set QT4_QTOPENGL_LIBRARY -+ FIND_LIBRARY(QT4_QTOPENGL_LIBRARY NAMES QtOpenGL QtOpenGL4 QtOpenGLd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ -+ # Set QT4_QTSQL_LIBRARY -+ FIND_LIBRARY(QT4_QTSQL_LIBRARY NAMES QtSql QtSql4 QtSqld4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ -+ # Set QT4_QTXML_LIBRARY -+ FIND_LIBRARY(QT4_QTXML_LIBRARY NAMES QtXml QtXml4 QtXmld4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ -+ # Set QT4_QTSVG_LIBRARY -+ FIND_LIBRARY(QT4_QTSVG_LIBRARY NAMES QtSvg QtSvg4 QtSvgd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ -+ # Set QT4_QTSCRIPT_LIBRARY -+ FIND_LIBRARY(QT4_QTSCRIPT_LIBRARY NAMES QtScript QtScript4 QtScriptd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ -+ # Set QT4_QTUITOOLS_LIBRARY -+ FIND_LIBRARY(QT4_QTUITOOLS_LIBRARY NAMES QtUiTools QtUiTools4 QtUiToolsd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ -+ # Set QT4_QTTEST_LIBRARY -+ FIND_LIBRARY(QT4_QTTEST_LIBRARY NAMES QtTest QtTest4 QtTestd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ -+ FIND_LIBRARY(QT4_QTDBUS_LIBRARY NAMES QtDBus QtDBus4 QtDBusd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ -+ IF(MSVC) -+ FIND_LIBRARY(QT4_QTCORE_LIBRARY_RELEASE NAMES QtCore4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTCORE_LIBRARY_DEBUG NAMES QtCored4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QT3SUPPORT_LIBRARY_RELEASE NAMES Qt3Support4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QT3SUPPORT_LIBRARY_DEBUG NAMES Qt3Supportd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTGUI_LIBRARY_RELEASE NAMES QtGui4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTGUI_LIBRARY_DEBUG NAMES QtGuid4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTNETWORK_LIBRARY_RELEASE NAMES QtNetwork4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTNETWORK_LIBRARY_DEBUG NAMES QtNetworkd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTOPENGL_LIBRARY_RELEASE NAMES QtOpenGL4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTOPENGL_LIBRARY_DEBUG NAMES QtOpenGLd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTSQL_LIBRARY_RELEASE NAMES QtSql4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTSQL_LIBRARY_DEBUG NAMES QtSqld4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTXML_LIBRARY_RELEASE NAMES QtXml4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTXML_LIBRARY_DEBUG NAMES QtXmld4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTSVG_LIBRARY_RELEASE NAMES QtSvg4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTSVG_LIBRARY_DEBUG NAMES QtSvgd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTSCRIPT_LIBRARY_RELEASE NAMES QtScript4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTSCRIPT_LIBRARY_DEBUG NAMES QtScriptd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTUITOOLS_LIBRARY_RELEASE NAMES QtUiTools QtUiTools4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTUITOOLS_LIBRARY_DEBUG NAMES QtUiToolsd QtUiToolsd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTTEST_LIBRARY_RELEASE NAMES QtTest4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTTEST_LIBRARY_DEBUG NAMES QtTestd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTDBUS_LIBRARY_RELEASE NAMES QtDBus4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTDBUS_LIBRARY_DEBUG NAMES QtDBusd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTASSISTANT_LIBRARY_RELEASE NAMES QtAssistantClient4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTASSISTANT_LIBRARY_DEBUG NAMES QtAssistantClientd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTDESIGNER_LIBRARY_RELEASE NAMES QtDesigner4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTDESIGNER_LIBRARY_DEBUG NAMES QtDesignerd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTDESIGNERCOMPONENTS_LIBRARY_RELEASE NAMES QtDesignerComponents4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTDESIGNERCOMPONENTS_LIBRARY_DEBUG NAMES QtDesignerComponentsd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTMAIN_LIBRARY_RELEASE NAMES qtmain PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ FIND_LIBRARY(QT4_QTMAIN_LIBRARY_DEBUG NAMES qtmaind PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ ENDIF(MSVC) -+ ENDIF (QT_USE_FRAMEWORKS) -+ -+ IF( NOT QT4_QTCORE_LIBRARY ) -+ IF( NOT Qt4_FIND_QUIETLY AND Qt4_FIND_REQUIRED) -+ MESSAGE( FATAL_ERROR "Could NOT find QtCore. Check ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log for more details.") -+ ENDIF( NOT Qt4_FIND_QUIETLY AND Qt4_FIND_REQUIRED) -+ ENDIF( NOT QT4_QTCORE_LIBRARY ) -+ -+ # Set QT4_QTASSISTANT_LIBRARY -+ FIND_LIBRARY(QT4_QTASSISTANT_LIBRARY NAMES QtAssistantClient QtAssistantClient4 QtAssistant QtAssistant4 QtAssistantd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ -+ # Set QT4_QTDESIGNER_LIBRARY -+ FIND_LIBRARY(QT4_QTDESIGNER_LIBRARY NAMES QtDesigner QtDesigner4 QtDesignerd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ -+ # Set QT4_QTDESIGNERCOMPONENTS_LIBRARY -+ FIND_LIBRARY(QT4_QTDESIGNERCOMPONENTS_LIBRARY NAMES QtDesignerComponents QtDesignerComponents4 QtDesignerComponentsd4 PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ -+ # Set QT4_QTMAIN_LIBRARY -+ IF(WIN32) -+ FIND_LIBRARY(QT4_QTMAIN_LIBRARY NAMES qtmain qtmaind PATHS ${QT4_LIBRARY_DIR} NO_DEFAULT_PATH) -+ ENDIF(WIN32) -+ -+ ############################################ -+ # -+ # Check the existence of the libraries. -+ # -+ ############################################ -+ -+ MACRO (_QT4_ADJUST_LIB_VARS basename) -+ IF (QT4_${basename}_LIBRARY OR QT4_${basename}_LIBRARY_DEBUG) -+ -+ IF(MSVC) -+ # Both set -+ IF (QT4_${basename}_LIBRARY_RELEASE AND QT4_${basename}_LIBRARY_DEBUG) -+ SET(QT4_${basename}_LIBRARY optimized ${QT4_${basename}_LIBRARY_RELEASE} debug ${QT4_${basename}_LIBRARY_DEBUG}) -+ ENDIF (QT4_${basename}_LIBRARY_RELEASE AND QT4_${basename}_LIBRARY_DEBUG) -+ -+ # Only debug was found -+ IF (NOT QT4_${basename}_LIBRARY_RELEASE AND QT4_${basename}_LIBRARY_DEBUG) -+ SET(QT4_${basename}_LIBRARY ${QT4_${basename}_LIBRARY_DEBUG}) -+ ENDIF (NOT QT4_${basename}_LIBRARY_RELEASE AND QT4_${basename}_LIBRARY_DEBUG) -+ -+ # Only release was found -+ IF (QT4_${basename}_LIBRARY_RELEASE AND NOT QT4_${basename}_LIBRARY_DEBUG) -+ SET(QT4_${basename}_LIBRARY ${QT4_${basename}_LIBRARY_RELEASE}) -+ ENDIF (QT4_${basename}_LIBRARY_RELEASE AND NOT QT4_${basename}_LIBRARY_DEBUG) -+ -+ # Hmm, is this used anywhere ? Yes, in UseQt4.cmake. We are currently incompatible :-( -+ SET(QT4_${basename}_LIBRARIES optimized ${QT4_${basename}_LIBRARY} debug ${QT4_${basename}_LIBRARY_DEBUG}) -+ -+ ENDIF(MSVC) -+ -+ SET(QT4_${basename}_LIBRARY ${QT4_${basename}_LIBRARY} CACHE FILEPATH "The Qt4 ${basename} library") -+ -+ IF (QT4_${basename}_LIBRARY) -+ SET(QT4_${basename}_FOUND 1) -+ ENDIF (QT4_${basename}_LIBRARY) -+ -+ ENDIF (QT4_${basename}_LIBRARY OR QT4_${basename}_LIBRARY_DEBUG) -+ -+ IF (QT4_${basename}_INCLUDE_DIR) -+ #add the include directory to QT4_INCLUDES -+ SET(QT4_INCLUDES "${QT4_${basename}_INCLUDE_DIR}" ${QT4_INCLUDES}) -+ ENDIF (QT4_${basename}_INCLUDE_DIR) -+ -+ # Make variables changeble to the advanced user -+ MARK_AS_ADVANCED(QT4_${basename}_LIBRARY QT4_${basename}_INCLUDE_DIR) -+ ENDMACRO (_QT4_ADJUST_LIB_VARS) -+ -+ -+ # Set QT_xyz_LIBRARY variable and add -+ # library include path to QT4_INCLUDES -+ _QT4_ADJUST_LIB_VARS(QTCORE) -+ _QT4_ADJUST_LIB_VARS(QTGUI) -+ _QT4_ADJUST_LIB_VARS(QT3SUPPORT) -+ _QT4_ADJUST_LIB_VARS(QTASSISTANT) -+ _QT4_ADJUST_LIB_VARS(QTDESIGNER) -+ _QT4_ADJUST_LIB_VARS(QTDESIGNERCOMPONENTS) -+ _QT4_ADJUST_LIB_VARS(QTNETWORK) -+ _QT4_ADJUST_LIB_VARS(QTNSPLUGIN) -+ _QT4_ADJUST_LIB_VARS(QTOPENGL) -+ _QT4_ADJUST_LIB_VARS(QTSQL) -+ _QT4_ADJUST_LIB_VARS(QTXML) -+ _QT4_ADJUST_LIB_VARS(QTSVG) -+ _QT4_ADJUST_LIB_VARS(QTSCRIPT) -+ _QT4_ADJUST_LIB_VARS(QTUITOOLS) -+ _QT4_ADJUST_LIB_VARS(QTTEST) -+ _QT4_ADJUST_LIB_VARS(QTDBUS) -+ -+ # platform dependent libraries -+ IF(Q_WS_X11) -+ _QT4_ADJUST_LIB_VARS(QTMOTIF) -+ ENDIF(Q_WS_X11) -+ IF(WIN32) -+ _QT4_ADJUST_LIB_VARS(QTMAIN) -+ ENDIF(WIN32) -+ -+ -+ ####################################### -+ # -+ # Check the executables of Qt -+ # ( moc, uic, rcc ) -+ # -+ ####################################### -+ -+ -+ # find moc and uic using qmake -+ QT_QUERY_QMAKE(QT4_MOC_EXECUTABLE_INTERNAL "QMAKE_MOC") -+ QT_QUERY_QMAKE(QT4_UIC_EXECUTABLE_INTERNAL "QMAKE_UIC") -+ -+ FILE(TO_CMAKE_PATH -+ "${QT4_MOC_EXECUTABLE_INTERNAL}" QT4_MOC_EXECUTABLE_INTERNAL) -+ FILE(TO_CMAKE_PATH -+ "${QT4_UIC_EXECUTABLE_INTERNAL}" QT4_UIC_EXECUTABLE_INTERNAL) -+ -+ SET(QT4_MOC_EXECUTABLE -+ ${QT4_MOC_EXECUTABLE_INTERNAL} CACHE FILEPATH "The moc executable") -+ SET(QT4_UIC_EXECUTABLE -+ ${QT4_UIC_EXECUTABLE_INTERNAL} CACHE FILEPATH "The uic executable") -+ -+ FIND_PROGRAM(QT_UIC3_EXECUTABLE -+ NAMES uic3 -+ PATHS ${QT_BINARY_DIR} -+ NO_DEFAULT_PATH -+ ) -+ -+ FIND_PROGRAM(QT_RCC_EXECUTABLE -+ NAMES rcc -+ PATHS ${QT_BINARY_DIR} -+ NO_DEFAULT_PATH -+ ) -+ -+ FIND_PROGRAM(QT_DBUSCPP2XML_EXECUTABLE -+ NAMES qdbuscpp2xml -+ PATHS ${QT_BINARY_DIR} -+ NO_DEFAULT_PATH -+ ) -+ -+ FIND_PROGRAM(QT_DBUSXML2CPP_EXECUTABLE -+ NAMES qdbusxml2cpp -+ PATHS ${QT_BINARY_DIR} -+ NO_DEFAULT_PATH -+ ) -+ -+ IF (QT4_MOC_EXECUTABLE) -+ SET(QT_WRAP_CPP "YES") -+ ENDIF (QT4_MOC_EXECUTABLE) -+ -+ IF (QT4_UIC_EXECUTABLE) -+ SET(QT_WRAP_UI "YES") -+ ENDIF (QT4_UIC_EXECUTABLE) -+ -+ -+ -+ MARK_AS_ADVANCED( QT4_UIC_EXECUTABLE QT_UIC3_EXECUTABLE QT4_MOC_EXECUTABLE QT_RCC_EXECUTABLE QT_DBUSXML2CPP_EXECUTABLE QT_DBUSCPP2XML_EXECUTABLE) -+ -+ ###################################### -+ # -+ # Macros for building Qt files -+ # -+ ###################################### -+ MACRO (QT4_EXTRACT_OPTIONS _qt4_files _qt4_options) -+ SET(${_qt4_files}) -+ SET(${_qt4_options}) -+ SET(_QT4_DOING_OPTIONS FALSE) -+ FOREACH(_currentArg ${ARGN}) -+ IF ("${_currentArg}" STREQUAL "OPTIONS") -+ SET(_QT4_DOING_OPTIONS TRUE) -+ ELSE ("${_currentArg}" STREQUAL "OPTIONS") -+ IF(_QT4_DOING_OPTIONS) -+ LIST(APPEND ${_qt4_options} "${_currentArg}") -+ ELSE(_QT4_DOING_OPTIONS) -+ LIST(APPEND ${_qt4_files} "${_currentArg}") -+ ENDIF(_QT4_DOING_OPTIONS) -+ ENDIF ("${_currentArg}" STREQUAL "OPTIONS") -+ ENDFOREACH(_currentArg) -+ ENDMACRO (QT4_EXTRACT_OPTIONS) -+ -+ MACRO (QT4_GET_MOC_INC_DIRS _moc_INC_DIRS) -+ SET(${_moc_INC_DIRS}) -+ GET_DIRECTORY_PROPERTY(_inc_DIRS INCLUDE_DIRECTORIES) -+ -+ FOREACH(_current ${_inc_DIRS}) -+ SET(${_moc_INC_DIRS} ${${_moc_INC_DIRS}} "-I" ${_current}) -+ ENDFOREACH(_current ${_inc_DIRS}) -+ -+ ENDMACRO(QT4_GET_MOC_INC_DIRS) -+ -+ -+ MACRO (QT4_GENERATE_MOC infile outfile ) -+ # get include dirs -+ QT4_GET_MOC_INC_DIRS(moc_includes) -+ -+ GET_FILENAME_COMPONENT(abs_infile ${infile} ABSOLUTE) -+ -+ IF (MSVC_IDE) -+ SET (_moc_parameter_file ${outfile}_parameters) -+ SET (_moc_param "${moc_includes} \n-o${outfile} \n${abs_infile}") -+ STRING(REGEX REPLACE ";-I;" "\\n-I" _moc_param "${_moc_param}") -+ FILE (WRITE ${_moc_parameter_file} "${_moc_param}") -+ ADD_CUSTOM_COMMAND(OUTPUT ${outfile} -+ COMMAND ${QT4_MOC_EXECUTABLE} -+ ARGS @"${_moc_parameter_file}" -+ DEPENDS ${abs_infile}) -+ ELSE (MSVC_IDE) -+ ADD_CUSTOM_COMMAND(OUTPUT ${outfile} -+ COMMAND ${QT4_MOC_EXECUTABLE} -+ ARGS ${moc_includes} -o ${outfile} ${abs_infile} -+ DEPENDS ${abs_infile}) -+ ENDIF (MSVC_IDE) -+ -+ SET_SOURCE_FILES_PROPERTIES(${outfile} PROPERTIES SKIP_AUTOMOC TRUE) # dont run automoc on this file -+ -+ MACRO_ADD_FILE_DEPENDENCIES(${abs_infile} ${outfile}) -+ ENDMACRO (QT4_GENERATE_MOC) -+ -+ -+ # QT4_WRAP_CPP(outfiles inputfile ... ) -+ # TODO perhaps add support for -D, -U and other minor options -+ -+ MACRO (QT4_WRAP_CPP outfiles ) -+ # get include dirs -+ QT4_GET_MOC_INC_DIRS(moc_includes) -+ QT4_EXTRACT_OPTIONS(moc_files moc_options ${ARGN}) -+ -+ FOREACH (it ${moc_files}) -+ GET_FILENAME_COMPONENT(it ${it} ABSOLUTE) -+ GET_FILENAME_COMPONENT(outfile ${it} NAME_WE) -+ -+ SET(outfile ${CMAKE_CURRENT_BINARY_DIR}/moc_${outfile}.cxx) -+ ADD_CUSTOM_COMMAND(OUTPUT ${outfile} -+ COMMAND ${QT4_MOC_EXECUTABLE} -+ ARGS ${moc_includes} ${moc_options} -o ${outfile} ${it} -+ DEPENDS ${it}) -+ SET(${outfiles} ${${outfiles}} ${outfile}) -+ ENDFOREACH(it) -+ -+ ENDMACRO (QT4_WRAP_CPP) -+ -+ -+ # QT4_WRAP_UI(outfiles inputfile ... ) -+ -+ MACRO (QT4_WRAP_UI outfiles ) -+ QT4_EXTRACT_OPTIONS(ui_files ui_options ${ARGN}) -+ -+ FOREACH (it ${ui_files}) -+ GET_FILENAME_COMPONENT(outfile ${it} NAME_WE) -+ GET_FILENAME_COMPONENT(infile ${it} ABSOLUTE) -+ SET(outfile ${CMAKE_CURRENT_BINARY_DIR}/ui_${outfile}.h) -+ ADD_CUSTOM_COMMAND(OUTPUT ${outfile} -+ COMMAND ${QT4_UIC_EXECUTABLE} -+ ARGS ${ui_options} -o ${outfile} ${infile} -+ MAIN_DEPENDENCY ${infile}) -+ SET(${outfiles} ${${outfiles}} ${outfile}) -+ ENDFOREACH (it) -+ -+ ENDMACRO (QT4_WRAP_UI) -+ -+ -+ # QT4_ADD_RESOURCES(outfiles inputfile ... ) -+ # TODO perhaps consider adding support for compression and root options to rcc -+ -+ MACRO (QT4_ADD_RESOURCES outfiles ) -+ QT4_EXTRACT_OPTIONS(rcc_files rcc_options ${ARGN}) -+ -+ FOREACH (it ${rcc_files}) -+ GET_FILENAME_COMPONENT(outfilename ${it} NAME_WE) -+ GET_FILENAME_COMPONENT(infile ${it} ABSOLUTE) -+ GET_FILENAME_COMPONENT(rc_path ${infile} PATH) -+ SET(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.cxx) -+ # parse file for dependencies -+ # all files are absolute paths or relative to the location of the qrc file -+ FILE(READ "${infile}" _RC_FILE_CONTENTS) -+ STRING(REGEX MATCHALL "]*>" "" _RC_FILE "${_RC_FILE}") -+ STRING(REGEX MATCH "^/|([A-Za-z]:/)" _ABS_PATH_INDICATOR "${_RC_FILE}") -+ IF(NOT _ABS_PATH_INDICATOR) -+ SET(_RC_FILE "${rc_path}/${_RC_FILE}") -+ ENDIF(NOT _ABS_PATH_INDICATOR) -+ SET(_RC_DEPENDS ${_RC_DEPENDS} "${_RC_FILE}") -+ ENDFOREACH(_RC_FILE) -+ ADD_CUSTOM_COMMAND(OUTPUT ${outfile} -+ COMMAND ${QT_RCC_EXECUTABLE} -+ ARGS ${rcc_options} -name ${outfilename} -o ${outfile} ${infile} -+ MAIN_DEPENDENCY ${infile} -+ DEPENDS ${_RC_DEPENDS}) -+ SET(${outfiles} ${${outfiles}} ${outfile}) -+ ENDFOREACH (it) -+ -+ ENDMACRO (QT4_ADD_RESOURCES) -+ -+ MACRO(QT4_ADD_DBUS_INTERFACE _sources _interface _basename) -+ GET_FILENAME_COMPONENT(_infile ${_interface} ABSOLUTE) -+ SET(_header ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.h) -+ SET(_impl ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.cpp) -+ SET(_moc ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.moc) -+ -+ GET_SOURCE_FILE_PROPERTY(_nonamespace ${_interface} NO_NAMESPACE) -+ IF ( _nonamespace ) -+ SET(_params -N -m) -+ ELSE ( _nonamespace ) -+ SET(_params -m) -+ ENDIF ( _nonamespace ) -+ -+ GET_SOURCE_FILE_PROPERTY(_include ${_interface} INCLUDE) -+ IF ( _include ) -+ SET(_params ${_params} -i ${_include}) -+ ENDIF ( _include ) -+ -+ ADD_CUSTOM_COMMAND(OUTPUT ${_impl} ${_header} -+ COMMAND ${QT_DBUSXML2CPP_EXECUTABLE} ${_params} -p ${_basename} ${_infile} -+ DEPENDS ${_infile}) -+ -+ SET_SOURCE_FILES_PROPERTIES(${_impl} PROPERTIES SKIP_AUTOMOC TRUE) -+ -+ QT4_GENERATE_MOC(${_header} ${_moc}) -+ -+ SET(${_sources} ${${_sources}} ${_impl} ${_header} ${_moc}) -+ MACRO_ADD_FILE_DEPENDENCIES(${_impl} ${_moc}) -+ -+ ENDMACRO(QT4_ADD_DBUS_INTERFACE) -+ -+ -+ MACRO(QT4_ADD_DBUS_INTERFACES _sources) -+ FOREACH (_current_FILE ${ARGN}) -+ GET_FILENAME_COMPONENT(_infile ${_current_FILE} ABSOLUTE) -+ # get the part before the ".xml" suffix -+ STRING(REGEX REPLACE "(.*[/\\.])?([^\\.]+)\\.xml" "\\2" _basename ${_current_FILE}) -+ STRING(TOLOWER ${_basename} _basename) -+ QT4_ADD_DBUS_INTERFACE(${_sources} ${_infile} ${_basename}interface) -+ ENDFOREACH (_current_FILE) -+ ENDMACRO(QT4_ADD_DBUS_INTERFACES) -+ -+ -+ MACRO(QT4_GENERATE_DBUS_INTERFACE _header) # _customName OPTIONS -some -options ) -+ QT4_EXTRACT_OPTIONS(_customName _qt4_dbus_options ${ARGN}) -+ -+ GET_FILENAME_COMPONENT(_in_file ${_header} ABSOLUTE) -+ GET_FILENAME_COMPONENT(_basename ${_header} NAME_WE) -+ -+ IF (_customName) -+ SET(_target ${CMAKE_CURRENT_BINARY_DIR}/${_customName}) -+ ELSE (_customName) -+ SET(_target ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.xml) -+ ENDIF (_customName) -+ -+ ADD_CUSTOM_COMMAND(OUTPUT ${_target} -+ COMMAND ${QT_DBUSCPP2XML_EXECUTABLE} ${_qt4_dbus_options} ${_in_file} > ${_target} -+ DEPENDS ${_in_file} -+ ) -+ ENDMACRO(QT4_GENERATE_DBUS_INTERFACE) -+ -+ -+ MACRO(QT4_ADD_DBUS_ADAPTOR _sources _xml_file _include _parentClass) # _optionalBasename _optionalClassName) -+ GET_FILENAME_COMPONENT(_infile ${_xml_file} ABSOLUTE) -+ -+ SET(_optionalBasename "${ARGV4}") -+ IF (_optionalBasename) -+ SET(_basename ${_optionalBasename} ) -+ ELSE (_optionalBasename) -+ STRING(REGEX REPLACE "(.*[/\\.])?([^\\.]+)\\.xml" "\\2adaptor" _basename ${_infile}) -+ STRING(TOLOWER ${_basename} _basename) -+ ENDIF (_optionalBasename) -+ -+ SET(_optionalClassName "${ARGV5}") -+ SET(_header ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.h) -+ SET(_impl ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.cpp) -+ SET(_moc ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.moc) -+ -+ IF(_optionalClassName) -+ ADD_CUSTOM_COMMAND(OUTPUT ${_impl} ${_header} -+ COMMAND ${QT_DBUSXML2CPP_EXECUTABLE} -m -a ${_basename} -c ${_optionalClassName} -i ${_include} -l ${_parentClass} ${_infile} -+ DEPENDS ${_infile} -+ ) -+ ELSE(_optionalClassName) -+ ADD_CUSTOM_COMMAND(OUTPUT ${_impl} ${_header} -+ COMMAND ${QT_DBUSXML2CPP_EXECUTABLE} -m -a ${_basename} -i ${_include} -l ${_parentClass} ${_infile} -+ DEPENDS ${_infile} -+ ) -+ ENDIF(_optionalClassName) -+ -+ QT4_GENERATE_MOC(${_header} ${_moc}) -+ SET_SOURCE_FILES_PROPERTIES(${_impl} PROPERTIES SKIP_AUTOMOC TRUE) -+ MACRO_ADD_FILE_DEPENDENCIES(${_impl} ${_moc}) -+ -+ SET(${_sources} ${${_sources}} ${_impl} ${_header} ${_moc}) -+ ENDMACRO(QT4_ADD_DBUS_ADAPTOR) -+ -+ MACRO(QT4_AUTOMOC) -+ QT4_GET_MOC_INC_DIRS(_moc_INCS) -+ -+ SET(_matching_FILES ) -+ FOREACH (_current_FILE ${ARGN}) -+ -+ GET_FILENAME_COMPONENT(_abs_FILE ${_current_FILE} ABSOLUTE) -+ # if "SKIP_AUTOMOC" is set to true, we will not handle this file here. -+ # here. this is required to make bouic work correctly: -+ # we need to add generated .cpp files to the sources (to compile them), -+ # but we cannot let automoc handle them, as the .cpp files don't exist yet when -+ # cmake is run for the very first time on them -> however the .cpp files might -+ # exist at a later run. at that time we need to skip them, so that we don't add two -+ # different rules for the same moc file -+ GET_SOURCE_FILE_PROPERTY(_skip ${_abs_FILE} SKIP_AUTOMOC) -+ -+ IF ( NOT _skip AND EXISTS ${_abs_FILE} ) -+ -+ FILE(READ ${_abs_FILE} _contents) -+ -+ GET_FILENAME_COMPONENT(_abs_PATH ${_abs_FILE} PATH) -+ -+ STRING(REGEX MATCHALL "#include +[^ ]+\\.moc[\">]" _match "${_contents}") -+ IF(_match) -+ FOREACH (_current_MOC_INC ${_match}) -+ STRING(REGEX MATCH "[^ <\"]+\\.moc" _current_MOC "${_current_MOC_INC}") -+ -+ GET_filename_component(_basename ${_current_MOC} NAME_WE) -+ # SET(_header ${CMAKE_CURRENT_SOURCE_DIR}/${_basename}.h) -+ IF (EXISTS ${_abs_PATH}/${_basename}.h) -+ SET(_header ${_abs_PATH}/${_basename}.h) -+ ELSE (EXISTS ${_abs_PATH}/${_basename}.h) -+ SET(_header ${_abs_FILE}) -+ ENDIF (EXISTS ${_abs_PATH}/${_basename}.h) -+ SET(_moc ${CMAKE_CURRENT_BINARY_DIR}/${_current_MOC}) -+ ADD_CUSTOM_COMMAND(OUTPUT ${_moc} -+ COMMAND ${QT4_MOC_EXECUTABLE} -+ ARGS ${_moc_INCS} ${_header} -o ${_moc} -+ DEPENDS ${_header} -+ ) -+ -+ MACRO_ADD_FILE_DEPENDENCIES(${_abs_FILE} ${_moc}) -+ ENDFOREACH (_current_MOC_INC) -+ ENDIF(_match) -+ ENDIF ( NOT _skip AND EXISTS ${_abs_FILE} ) -+ ENDFOREACH (_current_FILE) -+ ENDMACRO(QT4_AUTOMOC) -+ -+ -+ -+ ###################################### -+ # -+ # decide if Qt got found -+ # -+ ###################################### -+ -+ # if the includes,libraries,moc,uic and rcc are found then we have it -+ IF( QT4_LIBRARY_DIR AND QT4_INCLUDE_DIR AND QT4_MOC_EXECUTABLE AND QT4_UIC_EXECUTABLE AND QT_RCC_EXECUTABLE) -+ SET( QT4_FOUND "YES" ) -+ IF( NOT Qt4_FIND_QUIETLY) -+ MESSAGE(STATUS "Found Qt-Version ${QTVERSION} (using ${QT_QMAKE_EXECUTABLE})") -+ ENDIF( NOT Qt4_FIND_QUIETLY) -+ ELSE( QT4_LIBRARY_DIR AND QT4_INCLUDE_DIR AND QT4_MOC_EXECUTABLE AND QT4_UIC_EXECUTABLE AND QT_RCC_EXECUTABLE) -+ SET( QT4_FOUND "NO") -+ SET(QT_QMAKE_EXECUTABLE "${QT_QMAKE_EXECUTABLE}-NOTFOUND" CACHE FILEPATH "Invalid qmake found" FORCE) -+ IF( Qt4_FIND_REQUIRED) -+ IF ( NOT QT4_LIBRARY_DIR ) -+ MESSAGE(STATUS "Qt libraries NOT found!") -+ ENDIF(NOT QT4_LIBRARY_DIR ) -+ IF ( NOT QT4_INCLUDE_DIR ) -+ MESSAGE(STATUS "Qt includes NOT found!") -+ ENDIF( NOT QT4_INCLUDE_DIR ) -+ IF ( NOT QT4_MOC_EXECUTABLE ) -+ MESSAGE(STATUS "Qt's moc NOT found!") -+ ENDIF( NOT QT4_MOC_EXECUTABLE ) -+ IF ( NOT QT4_UIC_EXECUTABLE ) -+ MESSAGE(STATUS "Qt's uic NOT found!") -+ ENDIF( NOT QT4_UIC_EXECUTABLE ) -+ IF ( NOT QT_RCC_EXECUTABLE ) -+ MESSAGE(STATUS "Qt's rcc NOT found!") -+ ENDIF( NOT QT_RCC_EXECUTABLE ) -+ MESSAGE( FATAL_ERROR "Qt libraries, includes, moc, uic or/and rcc NOT found!") -+ ENDIF( Qt4_FIND_REQUIRED) -+ ENDIF( QT4_LIBRARY_DIR AND QT4_INCLUDE_DIR AND QT4_MOC_EXECUTABLE AND QT4_UIC_EXECUTABLE AND QT_RCC_EXECUTABLE) -+ SET(QT_FOUND ${QT4_FOUND}) -+ -+ -+ ####################################### -+ # -+ # System dependent settings -+ # -+ ####################################### -+ # for unix add X11 stuff -+ IF(UNIX) -+ # on OS X X11 may not be required -+ IF (Q_WS_X11) -+ FIND_PACKAGE(X11 REQUIRED) -+ ENDIF (Q_WS_X11) -+ FIND_PACKAGE(Threads) -+ SET(QT4_QTCORE_LIBRARY ${QT4_QTCORE_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) -+ ENDIF(UNIX) -+ -+ -+ ####################################### -+ # -+ # compatibility settings -+ # -+ ####################################### -+ # Backwards compatibility for CMake1.4 and 1.2 -+ SET (QT_MOC_EXE ${QT4_MOC_EXECUTABLE} ) -+ SET (QT_UIC_EXE ${QT4_UIC_EXECUTABLE} ) -+ -+ SET( QT4_QT_LIBRARY "") -+ -+ELSE(QT4_QMAKE_FOUND) -+ -+ SET(QT_QMAKE_EXECUTABLE "${QT_QMAKE_EXECUTABLE}-NOTFOUND" CACHE FILEPATH "Invalid qmake found" FORCE) -+ IF(Qt4_FIND_REQUIRED) -+ IF(QT4_INSTALLED_VERSION_TOO_OLD) -+ MESSAGE(FATAL_ERROR "The installed Qt version ${QTVERSION} is too old, at least version ${QT4_MIN_VERSION} is required") -+ ELSE(QT4_INSTALLED_VERSION_TOO_OLD) -+ MESSAGE( FATAL_ERROR "Qt qmake not found!") -+ ENDIF(QT4_INSTALLED_VERSION_TOO_OLD) -+ ELSE(Qt4_FIND_REQUIRED) -+ IF(QT4_INSTALLED_VERSION_TOO_OLD AND NOT Qt4_FIND_QUIETLY) -+ MESSAGE(STATUS "The installed Qt version ${QTVERSION} is too old, at least version ${QT4_MIN_VERSION} is required") -+ ENDIF(QT4_INSTALLED_VERSION_TOO_OLD AND NOT Qt4_FIND_QUIETLY) -+ ENDIF(Qt4_FIND_REQUIRED) -+ -+ENDIF (QT4_QMAKE_FOUND) -+ENDIF (QT4_QMAKE_FOUND) -+ -diff --git a/poppler-qt4.pc.cmake b/poppler-qt4.pc.cmake -new file mode 100644 -index 00000000..46a37f6d ---- /dev/null -+++ b/poppler-qt4.pc.cmake -@@ -0,0 +1,12 @@ -+prefix=@CMAKE_INSTALL_PREFIX@ -+libdir=@CMAKE_INSTALL_FULL_LIBDIR@ -+includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ -+ -+Name: poppler-qt4 -+Description: Qt4 bindings for poppler -+Version: @POPPLER_VERSION@ -+Requires: @PC_REQUIRES@ -+@PC_REQUIRES_PRIVATE@ -+ -+Libs: -L${libdir} -lpoppler-qt4 -+Cflags: -I${includedir}/poppler/qt4 -diff --git a/qt4/.gitignore b/qt4/.gitignore -new file mode 100644 -index 00000000..5540f35d ---- /dev/null -+++ b/qt4/.gitignore -@@ -0,0 +1,4 @@ -+Makefile -+Makefile.in -+*~ -+ -diff --git a/qt4/CMakeLists.txt b/qt4/CMakeLists.txt -new file mode 100644 -index 00000000..4d345681 ---- /dev/null -+++ b/qt4/CMakeLists.txt -@@ -0,0 +1,6 @@ -+# Qt4 headers are not override clean so disable suggest-override if it's there -+string(REPLACE "-Wsuggest-override" " " CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) -+ -+add_subdirectory(src) -+add_subdirectory(tests) -+add_subdirectory(demos) -diff --git a/qt4/demos/.gitignore b/qt4/demos/.gitignore -new file mode 100644 -index 00000000..9639e685 ---- /dev/null -+++ b/qt4/demos/.gitignore -@@ -0,0 +1,4 @@ -+.deps -+.libs -+*moc -+poppler_qt4viewer -diff --git a/qt4/demos/CMakeLists.txt b/qt4/demos/CMakeLists.txt -new file mode 100644 -index 00000000..76accf81 ---- /dev/null -+++ b/qt4/demos/CMakeLists.txt -@@ -0,0 +1,28 @@ -+add_definitions(${QT4_DEFINITIONS}) -+ -+include_directories( -+ ${CMAKE_CURRENT_SOURCE_DIR} -+ ${CMAKE_CURRENT_SOURCE_DIR}/../src -+ ${CMAKE_CURRENT_BINARY_DIR} -+ ${QT4_INCLUDE_DIR} -+) -+ -+set(poppler_qt4viewer_SRCS -+ abstractinfodock.cpp -+ documentobserver.cpp -+ embeddedfiles.cpp -+ fonts.cpp -+ info.cpp -+ main_viewer.cpp -+ metadata.cpp -+ navigationtoolbar.cpp -+ optcontent.cpp -+ pageview.cpp -+ permissions.cpp -+ thumbnails.cpp -+ toc.cpp -+ viewer.cpp -+) -+qt4_automoc(${poppler_qt4viewer_SRCS}) -+poppler_add_test(poppler_qt4viewer BUILD_QT4_TESTS ${poppler_qt4viewer_SRCS}) -+target_link_libraries(poppler_qt4viewer poppler-qt4) -diff --git a/qt4/demos/abstractinfodock.cpp b/qt4/demos/abstractinfodock.cpp -new file mode 100644 -index 00000000..7b306d82 ---- /dev/null -+++ b/qt4/demos/abstractinfodock.cpp -@@ -0,0 +1,57 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 "fonts.h" -+ -+AbstractInfoDock::AbstractInfoDock(QWidget *parent) -+ : QDockWidget(parent), m_filled(false) -+{ -+ connect(this, SIGNAL(visibilityChanged(bool)), SLOT(slotVisibilityChanged(bool))); -+} -+ -+AbstractInfoDock::~AbstractInfoDock() -+{ -+} -+ -+void AbstractInfoDock::documentLoaded() -+{ -+ if (!isHidden()) { -+ fillInfo(); -+ m_filled = true; -+ } -+} -+ -+void AbstractInfoDock::documentClosed() -+{ -+ m_filled = false; -+} -+ -+void AbstractInfoDock::pageChanged(int page) -+{ -+ Q_UNUSED(page) -+} -+ -+void AbstractInfoDock::slotVisibilityChanged(bool visible) -+{ -+ if (visible && document() && !m_filled) { -+ fillInfo(); -+ m_filled = true; -+ } -+} -+ -+#include "abstractinfodock.moc" -diff --git a/qt4/demos/abstractinfodock.h b/qt4/demos/abstractinfodock.h -new file mode 100644 -index 00000000..2593325a ---- /dev/null -+++ b/qt4/demos/abstractinfodock.h -@@ -0,0 +1,48 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 ABSTRACTINFODOCK_H -+#define ABSTRACTINFODOCK_H -+ -+#include -+ -+#include "documentobserver.h" -+ -+class AbstractInfoDock : public QDockWidget, public DocumentObserver -+{ -+ Q_OBJECT -+ -+public: -+ AbstractInfoDock(QWidget *parent = 0); -+ ~AbstractInfoDock(); -+ -+ /*virtual*/ void documentLoaded(); -+ /*virtual*/ void documentClosed(); -+ /*virtual*/ void pageChanged(int page); -+ -+protected: -+ virtual void fillInfo() = 0; -+ -+private Q_SLOTS: -+ void slotVisibilityChanged(bool visible); -+ -+private: -+ bool m_filled; -+}; -+ -+#endif -diff --git a/qt4/demos/documentobserver.cpp b/qt4/demos/documentobserver.cpp -new file mode 100644 -index 00000000..e5c283db ---- /dev/null -+++ b/qt4/demos/documentobserver.cpp -@@ -0,0 +1,50 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 "documentobserver.h" -+ -+#include "viewer.h" -+ -+DocumentObserver::DocumentObserver() -+ : m_viewer(0) -+{ -+} -+ -+DocumentObserver::~DocumentObserver() -+{ -+} -+ -+Poppler::Document* DocumentObserver::document() const -+{ -+ return m_viewer->m_doc; -+} -+ -+void DocumentObserver::setPage(int page) -+{ -+ m_viewer->setPage(page); -+} -+ -+int DocumentObserver::page() const -+{ -+ return m_viewer->page(); -+} -+ -+void DocumentObserver::reloadPage() -+{ -+ m_viewer->setPage(m_viewer->page()); -+} -diff --git a/qt4/demos/documentobserver.h b/qt4/demos/documentobserver.h -new file mode 100644 -index 00000000..38fe2043 ---- /dev/null -+++ b/qt4/demos/documentobserver.h -@@ -0,0 +1,50 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 DOCUMENTOBSERVER_H -+#define DOCUMENTOBSERVER_H -+ -+class PdfViewer; -+namespace Poppler { -+class Document; -+} -+ -+class DocumentObserver -+{ -+friend class PdfViewer; -+ -+public: -+ virtual ~DocumentObserver(); -+ -+ virtual void documentLoaded() = 0; -+ virtual void documentClosed() = 0; -+ virtual void pageChanged(int page) = 0; -+ -+protected: -+ DocumentObserver(); -+ -+ Poppler::Document* document() const; -+ void setPage(int page); -+ int page() const; -+ void reloadPage(); -+ -+private: -+ PdfViewer *m_viewer; -+}; -+ -+#endif -diff --git a/qt4/demos/embeddedfiles.cpp b/qt4/demos/embeddedfiles.cpp -new file mode 100644 -index 00000000..22f9da7a ---- /dev/null -+++ b/qt4/demos/embeddedfiles.cpp -@@ -0,0 +1,82 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 "embeddedfiles.h" -+ -+#include -+ -+#include -+ -+EmbeddedFilesDock::EmbeddedFilesDock(QWidget *parent) -+ : AbstractInfoDock(parent) -+{ -+ m_table = new QTableWidget(this); -+ setWidget(m_table); -+ setWindowTitle(tr("Embedded files")); -+ m_table->setColumnCount(6); -+ m_table->setHorizontalHeaderLabels( -+ QStringList() << tr("Name") << tr("Description") << tr("Size") << tr("Creation date") -+ << tr("Modification date") << tr("Checksum")); -+ m_table->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); -+} -+ -+EmbeddedFilesDock::~EmbeddedFilesDock() -+{ -+} -+ -+void EmbeddedFilesDock::fillInfo() -+{ -+ m_table->setHorizontalHeaderLabels( -+ QStringList() << tr("Name") << tr("Description") << tr("Size") << tr("Creation date") -+ << tr("Modification date") << tr("Checksum")); -+ if (!document()->hasEmbeddedFiles()) { -+ m_table->setItem(0, 0, new QTableWidgetItem(tr("No files"))); -+ return; -+ } -+ -+ const QList files = document()->embeddedFiles(); -+ m_table->setRowCount(files.count()); -+ int i = 0; -+ Q_FOREACH(Poppler::EmbeddedFile *file, files) { -+ m_table->setItem(i, 0, new QTableWidgetItem(file->name())); -+ m_table->setItem(i, 1, new QTableWidgetItem(file->description())); -+ m_table->setItem(i, 2, new QTableWidgetItem(QString::number(file->size()))); -+ m_table->setItem(i, 3, new QTableWidgetItem(file->createDate().toString(Qt::SystemLocaleDate))); -+ m_table->setItem(i, 4, new QTableWidgetItem(file->modDate().toString(Qt::SystemLocaleDate))); -+ const QByteArray checksum = file->checksum(); -+ const QString checksumString = !checksum.isEmpty() ? QString::fromAscii(checksum.toHex()) : QString::fromLatin1("n/a"); -+ m_table->setItem(i, 5, new QTableWidgetItem(checksumString)); -+ ++i; -+ } -+} -+ -+void EmbeddedFilesDock::documentLoaded() -+{ -+ if ( document()->pageMode() == Poppler::Document::UseAttach ) { -+ show(); -+ } -+} -+ -+void EmbeddedFilesDock::documentClosed() -+{ -+ m_table->clear(); -+ m_table->setRowCount(0); -+ AbstractInfoDock::documentClosed(); -+} -+ -+#include "embeddedfiles.moc" -diff --git a/qt4/demos/embeddedfiles.h b/qt4/demos/embeddedfiles.h -new file mode 100644 -index 00000000..7cd60397 ---- /dev/null -+++ b/qt4/demos/embeddedfiles.h -@@ -0,0 +1,44 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 ATTACHMENTS_H -+#define ATTACHMENTS_H -+ -+#include "abstractinfodock.h" -+ -+class QTableWidget; -+ -+class EmbeddedFilesDock : public AbstractInfoDock -+{ -+ Q_OBJECT -+ -+public: -+ EmbeddedFilesDock(QWidget *parent = 0); -+ ~EmbeddedFilesDock(); -+ -+ virtual void documentLoaded(); -+ /*virtual*/ void documentClosed(); -+ -+protected: -+ /*virtual*/ void fillInfo(); -+ -+private: -+ QTableWidget *m_table; -+}; -+ -+#endif -diff --git a/qt4/demos/fonts.cpp b/qt4/demos/fonts.cpp -new file mode 100644 -index 00000000..bd342bd2 ---- /dev/null -+++ b/qt4/demos/fonts.cpp -@@ -0,0 +1,72 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 "fonts.h" -+ -+#include -+ -+#include -+ -+static QString yesNoStatement(bool value) -+{ -+ return value ? QString::fromLatin1("yes") : QString::fromLatin1("no"); -+} -+ -+FontsDock::FontsDock(QWidget *parent) -+ : AbstractInfoDock(parent) -+{ -+ m_table = new QTableWidget(this); -+ setWidget(m_table); -+ setWindowTitle(tr("Fonts")); -+ m_table->setColumnCount(5); -+ m_table->setHorizontalHeaderLabels(QStringList() << tr("Name") << tr("Type") << tr("Embedded") << tr("Subset") << tr("File")); -+ m_table->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); -+} -+ -+FontsDock::~FontsDock() -+{ -+} -+ -+void FontsDock::fillInfo() -+{ -+ const QList fonts = document()->fonts(); -+ m_table->setHorizontalHeaderLabels(QStringList() << tr("Name") << tr("Type") << tr("Embedded") << tr("Subset") << tr("File")); -+ m_table->setRowCount(fonts.count()); -+ int i = 0; -+ Q_FOREACH(const Poppler::FontInfo &font, fonts) { -+ if (font.name().isNull()) { -+ m_table->setItem(i, 0, new QTableWidgetItem(QString::fromLatin1("[none]"))); -+ } else { -+ m_table->setItem(i, 0, new QTableWidgetItem(font.name())); -+ } -+ m_table->setItem(i, 1, new QTableWidgetItem(font.typeName())); -+ m_table->setItem(i, 2, new QTableWidgetItem(yesNoStatement(font.isEmbedded()))); -+ m_table->setItem(i, 3, new QTableWidgetItem(yesNoStatement(font.isSubset()))); -+ m_table->setItem(i, 4, new QTableWidgetItem(font.file())); -+ ++i; -+ } -+} -+ -+void FontsDock::documentClosed() -+{ -+ m_table->clear(); -+ m_table->setRowCount(0); -+ AbstractInfoDock::documentClosed(); -+} -+ -+#include "fonts.moc" -diff --git a/qt4/demos/fonts.h b/qt4/demos/fonts.h -new file mode 100644 -index 00000000..81afa579 ---- /dev/null -+++ b/qt4/demos/fonts.h -@@ -0,0 +1,43 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 FONTS_H -+#define FONTS_H -+ -+#include "abstractinfodock.h" -+ -+class QTableWidget; -+ -+class FontsDock : public AbstractInfoDock -+{ -+ Q_OBJECT -+ -+public: -+ FontsDock(QWidget *parent = 0); -+ ~FontsDock(); -+ -+ /*virtual*/ void documentClosed(); -+ -+protected: -+ /*virtual*/ void fillInfo(); -+ -+private: -+ QTableWidget *m_table; -+}; -+ -+#endif -diff --git a/qt4/demos/info.cpp b/qt4/demos/info.cpp -new file mode 100644 -index 00000000..6491e0e4 ---- /dev/null -+++ b/qt4/demos/info.cpp -@@ -0,0 +1,72 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 "info.h" -+ -+#include -+ -+#include -+ -+InfoDock::InfoDock(QWidget *parent) -+ : AbstractInfoDock(parent) -+{ -+ m_table = new QTableWidget(this); -+ setWidget(m_table); -+ setWindowTitle(tr("Information")); -+ m_table->setColumnCount(2); -+ m_table->setHorizontalHeaderLabels(QStringList() << tr("Key") << tr("Value")); -+ m_table->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); -+} -+ -+InfoDock::~InfoDock() -+{ -+} -+ -+void InfoDock::fillInfo() -+{ -+ QStringList keys = document()->infoKeys(); -+ m_table->setHorizontalHeaderLabels(QStringList() << tr("Key") << tr("Value")); -+ m_table->setRowCount(keys.count()); -+ QStringList dateKeys; -+ dateKeys << QString::fromLatin1("CreationDate"); -+ dateKeys << QString::fromLatin1("ModDate"); -+ int i = 0; -+ Q_FOREACH(const QString &date, dateKeys) { -+ const int id = keys.indexOf(date); -+ if (id != -1) { -+ m_table->setItem(i, 0, new QTableWidgetItem(date)); -+ m_table->setItem(i, 1, new QTableWidgetItem(document()->date(date).toString(Qt::SystemLocaleDate))); -+ ++i; -+ keys.removeAt(id); -+ } -+ } -+ Q_FOREACH(const QString &key, keys) { -+ m_table->setItem(i, 0, new QTableWidgetItem(key)); -+ m_table->setItem(i, 1, new QTableWidgetItem(document()->info(key))); -+ ++i; -+ } -+} -+ -+void InfoDock::documentClosed() -+{ -+ m_table->clear(); -+ m_table->setRowCount(0); -+ AbstractInfoDock::documentClosed(); -+} -+ -+#include "info.moc" -diff --git a/qt4/demos/info.h b/qt4/demos/info.h -new file mode 100644 -index 00000000..d294b430 ---- /dev/null -+++ b/qt4/demos/info.h -@@ -0,0 +1,43 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 INFO_H -+#define INFO_H -+ -+#include "abstractinfodock.h" -+ -+class QTableWidget; -+ -+class InfoDock : public AbstractInfoDock -+{ -+ Q_OBJECT -+ -+public: -+ InfoDock(QWidget *parent = 0); -+ ~InfoDock(); -+ -+ /*virtual*/ void documentClosed(); -+ -+protected: -+ /*virtual*/ void fillInfo(); -+ -+private: -+ QTableWidget *m_table; -+}; -+ -+#endif -diff --git a/qt4/demos/main_viewer.cpp b/qt4/demos/main_viewer.cpp -new file mode 100644 -index 00000000..3f7080f2 ---- /dev/null -+++ b/qt4/demos/main_viewer.cpp -@@ -0,0 +1,33 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 "viewer.h" -+ -+#include -+ -+int main(int argc, char *argv[]) -+{ -+ QApplication app(argc, argv); -+ const QStringList args = QCoreApplication::arguments(); -+ PdfViewer *viewer = new PdfViewer(); -+ viewer->show(); -+ if (args.count() > 1) { -+ viewer->loadDocument(args.at(1)); -+ } -+ return app.exec(); -+} -diff --git a/qt4/demos/metadata.cpp b/qt4/demos/metadata.cpp -new file mode 100644 -index 00000000..e5c7111d ---- /dev/null -+++ b/qt4/demos/metadata.cpp -@@ -0,0 +1,50 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 "metadata.h" -+ -+#include -+ -+#include -+ -+MetadataDock::MetadataDock(QWidget *parent) -+ : AbstractInfoDock(parent) -+{ -+ m_edit = new QTextEdit(this); -+ setWidget(m_edit); -+ setWindowTitle(tr("Metadata")); -+ m_edit->setAcceptRichText(false); -+ m_edit->setReadOnly(true); -+} -+ -+MetadataDock::~MetadataDock() -+{ -+} -+ -+void MetadataDock::fillInfo() -+{ -+ m_edit->setPlainText(document()->metadata()); -+} -+ -+void MetadataDock::documentClosed() -+{ -+ m_edit->clear(); -+ AbstractInfoDock::documentClosed(); -+} -+ -+#include "metadata.moc" -diff --git a/qt4/demos/metadata.h b/qt4/demos/metadata.h -new file mode 100644 -index 00000000..6f1507a6 ---- /dev/null -+++ b/qt4/demos/metadata.h -@@ -0,0 +1,43 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 METADATA_H -+#define METADATA_H -+ -+#include "abstractinfodock.h" -+ -+class QTextEdit; -+ -+class MetadataDock : public AbstractInfoDock -+{ -+ Q_OBJECT -+ -+public: -+ MetadataDock(QWidget *parent = 0); -+ ~MetadataDock(); -+ -+ /*virtual*/ void documentClosed(); -+ -+protected: -+ /*virtual*/ void fillInfo(); -+ -+private: -+ QTextEdit *m_edit; -+}; -+ -+#endif -diff --git a/qt4/demos/navigationtoolbar.cpp b/qt4/demos/navigationtoolbar.cpp -new file mode 100644 -index 00000000..79dd418a ---- /dev/null -+++ b/qt4/demos/navigationtoolbar.cpp -@@ -0,0 +1,144 @@ -+/* -+ * Copyright (C) 2008-2009, Pino Toscano -+ * Copyright (C) 2013, Fabio D'Urso -+ * -+ * 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 "navigationtoolbar.h" -+ -+#include -+ -+#include -+#include -+ -+NavigationToolBar::NavigationToolBar(QWidget *parent) -+ : QToolBar(parent) -+{ -+ m_firstAct = addAction(tr("First"), this, SLOT(slotGoFirst())); -+ m_prevAct = addAction(tr("Previous"), this, SLOT(slotGoPrev())); -+ m_pageCombo = new QComboBox(this); -+ connect(m_pageCombo, SIGNAL(activated(int)), this, SLOT(slotComboActivated(int))); -+ addWidget(m_pageCombo); -+ m_nextAct = addAction(tr("Next"), this, SLOT(slotGoNext())); -+ m_lastAct = addAction(tr("Last"), this, SLOT(slotGoLast())); -+ -+ addSeparator(); -+ -+ m_zoomCombo = new QComboBox(this); -+ m_zoomCombo->setEditable(true); -+ m_zoomCombo->addItem(tr("10%")); -+ m_zoomCombo->addItem(tr("25%")); -+ m_zoomCombo->addItem(tr("33%")); -+ m_zoomCombo->addItem(tr("50%")); -+ m_zoomCombo->addItem(tr("66%")); -+ m_zoomCombo->addItem(tr("75%")); -+ m_zoomCombo->addItem(tr("100%")); -+ m_zoomCombo->addItem(tr("125%")); -+ m_zoomCombo->addItem(tr("150%")); -+ m_zoomCombo->addItem(tr("200%")); -+ m_zoomCombo->addItem(tr("300%")); -+ m_zoomCombo->addItem(tr("400%")); -+ m_zoomCombo->setCurrentIndex(6); // "100%" -+ connect(m_zoomCombo, SIGNAL(currentIndexChanged(QString)), this, SLOT(slotZoomComboChanged(QString))); -+ addWidget(m_zoomCombo); -+ -+ m_rotationCombo = new QComboBox(this); -+ // NOTE: \302\260 = degree symbol -+ m_rotationCombo->addItem(trUtf8("0\302\260")); -+ m_rotationCombo->addItem(trUtf8("90\302\260")); -+ m_rotationCombo->addItem(trUtf8("180\302\260")); -+ m_rotationCombo->addItem(trUtf8("270\302\260")); -+ connect(m_rotationCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(slotRotationComboChanged(int))); -+ addWidget(m_rotationCombo); -+ -+ documentClosed(); -+} -+ -+NavigationToolBar::~NavigationToolBar() -+{ -+} -+ -+void NavigationToolBar::documentLoaded() -+{ -+ const int pageCount = document()->numPages(); -+ for (int i = 0; i < pageCount; ++i) { -+ m_pageCombo->addItem(QString::number(i + 1)); -+ } -+ m_pageCombo->setEnabled(true); -+} -+ -+void NavigationToolBar::documentClosed() -+{ -+ m_firstAct->setEnabled(false); -+ m_prevAct->setEnabled(false); -+ m_nextAct->setEnabled(false); -+ m_lastAct->setEnabled(false); -+ m_pageCombo->clear(); -+ m_pageCombo->setEnabled(false); -+} -+ -+void NavigationToolBar::pageChanged(int page) -+{ -+ const int pageCount = document()->numPages(); -+ m_firstAct->setEnabled(page > 0); -+ m_prevAct->setEnabled(page > 0); -+ m_nextAct->setEnabled(page < (pageCount - 1)); -+ m_lastAct->setEnabled(page < (pageCount - 1)); -+ m_pageCombo->setCurrentIndex(page); -+} -+ -+void NavigationToolBar::slotGoFirst() -+{ -+ setPage(0); -+} -+ -+void NavigationToolBar::slotGoPrev() -+{ -+ setPage(page() - 1); -+} -+ -+void NavigationToolBar::slotGoNext() -+{ -+ setPage(page() + 1); -+} -+ -+void NavigationToolBar::slotGoLast() -+{ -+ setPage(document()->numPages() - 1); -+} -+ -+void NavigationToolBar::slotComboActivated(int index) -+{ -+ setPage(index); -+} -+ -+void NavigationToolBar::slotZoomComboChanged(const QString &_text) -+{ -+ QString text = _text; -+ text.remove(QLatin1Char('%')); -+ bool ok = false; -+ int value = text.toInt(&ok); -+ if (ok && value >= 10) { -+ emit zoomChanged(qreal(value) / 100); -+ } -+} -+ -+void NavigationToolBar::slotRotationComboChanged(int idx) -+{ -+ emit rotationChanged(idx * 90); -+} -+ -+#include "navigationtoolbar.moc" -diff --git a/qt4/demos/navigationtoolbar.h b/qt4/demos/navigationtoolbar.h -new file mode 100644 -index 00000000..d7dbd5dd ---- /dev/null -+++ b/qt4/demos/navigationtoolbar.h -@@ -0,0 +1,65 @@ -+/* -+ * Copyright (C) 2008-2009, Pino Toscano -+ * Copyright (C) 2013, Fabio D'Urso -+ * -+ * 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 NAVIGATIONTOOLBAR_H -+#define NAVIGATIONTOOLBAR_H -+ -+#include -+ -+#include "documentobserver.h" -+ -+class QAction; -+class QComboBox; -+ -+class NavigationToolBar : public QToolBar, public DocumentObserver -+{ -+ Q_OBJECT -+ -+public: -+ NavigationToolBar(QWidget *parent = 0); -+ ~NavigationToolBar(); -+ -+ /*virtual*/ void documentLoaded(); -+ /*virtual*/ void documentClosed(); -+ /*virtual*/ void pageChanged(int page); -+ -+Q_SIGNALS: -+ void zoomChanged(qreal value); -+ void rotationChanged(int rotation); -+ -+private Q_SLOTS: -+ void slotGoFirst(); -+ void slotGoPrev(); -+ void slotGoNext(); -+ void slotGoLast(); -+ void slotComboActivated(int index); -+ void slotZoomComboChanged(const QString &text); -+ void slotRotationComboChanged(int idx); -+ -+private: -+ QAction *m_firstAct; -+ QAction *m_prevAct; -+ QComboBox *m_pageCombo; -+ QAction *m_nextAct; -+ QAction *m_lastAct; -+ QComboBox *m_zoomCombo; -+ QComboBox *m_rotationCombo; -+}; -+ -+#endif -diff --git a/qt4/demos/optcontent.cpp b/qt4/demos/optcontent.cpp -new file mode 100644 -index 00000000..0c1015b9 ---- /dev/null -+++ b/qt4/demos/optcontent.cpp -@@ -0,0 +1,69 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 "optcontent.h" -+ -+#include -+ -+#include -+ -+OptContentDock::OptContentDock(QWidget *parent) -+ : AbstractInfoDock(parent) -+{ -+ m_view = new QTreeView(this); -+ setWidget(m_view); -+ setWindowTitle(tr("Optional content")); -+ m_view->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); -+} -+ -+OptContentDock::~OptContentDock() -+{ -+} -+ -+ -+void OptContentDock::documentLoaded() -+{ -+ AbstractInfoDock::documentLoaded(); -+ if ( document()->pageMode() == Poppler::Document::UseOC ) { -+ show(); -+ } -+} -+ -+void OptContentDock::fillInfo() -+{ -+ if (!document()->hasOptionalContent()) { -+ return; -+ } -+ -+ m_view->setModel(document()->optionalContentModel()); -+ connect(m_view->model(), SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(reloadImage())); -+ m_view->expandToDepth(1); -+} -+ -+void OptContentDock::documentClosed() -+{ -+ m_view->setModel(0); -+ AbstractInfoDock::documentClosed(); -+} -+ -+void OptContentDock::reloadImage() -+{ -+ reloadPage(); -+} -+ -+#include "optcontent.moc" -diff --git a/qt4/demos/optcontent.h b/qt4/demos/optcontent.h -new file mode 100644 -index 00000000..b933f5cd ---- /dev/null -+++ b/qt4/demos/optcontent.h -@@ -0,0 +1,47 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 OPTCONTENT_H -+#define OPTCONTENT_H -+ -+#include "abstractinfodock.h" -+ -+class QTreeView; -+ -+class OptContentDock : public AbstractInfoDock -+{ -+ Q_OBJECT -+ -+public: -+ OptContentDock(QWidget *parent = 0); -+ ~OptContentDock(); -+ -+ /*virtual*/ void documentLoaded(); -+ /*virtual*/ void documentClosed(); -+ -+protected: -+ /*virtual*/ void fillInfo(); -+ -+private Q_SLOTS: -+ void reloadImage(); -+ -+private: -+ QTreeView *m_view; -+}; -+ -+#endif -diff --git a/qt4/demos/pageview.cpp b/qt4/demos/pageview.cpp -new file mode 100644 -index 00000000..0dfa5e9e ---- /dev/null -+++ b/qt4/demos/pageview.cpp -@@ -0,0 +1,101 @@ -+/* -+ * Copyright (C) 2008-2009, Pino Toscano -+ * Copyright (C) 2013, Fabio D'Urso -+ * -+ * 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 "pageview.h" -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+PageView::PageView(QWidget *parent) -+ : QScrollArea(parent) -+ , m_zoom(1.0) -+ , m_rotation(0) -+ , m_dpiX(QApplication::desktop()->physicalDpiX()) -+ , m_dpiY(QApplication::desktop()->physicalDpiY()) -+{ -+ m_imageLabel = new QLabel(this); -+ m_imageLabel->resize(0, 0); -+ setWidget(m_imageLabel); -+} -+ -+PageView::~PageView() -+{ -+} -+ -+void PageView::documentLoaded() -+{ -+} -+ -+void PageView::documentClosed() -+{ -+ m_imageLabel->clear(); -+ m_imageLabel->resize(0, 0); -+} -+ -+void PageView::pageChanged(int page) -+{ -+ Poppler::Page *popplerPage = document()->page(page); -+ const double resX = m_dpiX * m_zoom; -+ const double resY = m_dpiY * m_zoom; -+ -+ Poppler::Page::Rotation rot; -+ if (m_rotation == 0) -+ rot = Poppler::Page::Rotate0; -+ else if (m_rotation == 90) -+ rot = Poppler::Page::Rotate90; -+ else if (m_rotation == 180) -+ rot = Poppler::Page::Rotate180; -+ else // m_rotation == 270 -+ rot = Poppler::Page::Rotate270; -+ -+ QImage image = popplerPage->renderToImage(resX, resY, -1, -1, -1, -1, rot); -+ if (!image.isNull()) { -+ m_imageLabel->resize(image.size()); -+ m_imageLabel->setPixmap(QPixmap::fromImage(image)); -+ } else { -+ m_imageLabel->resize(0, 0); -+ m_imageLabel->setPixmap(QPixmap()); -+ } -+ delete popplerPage; -+} -+ -+void PageView::slotZoomChanged(qreal value) -+{ -+ m_zoom = value; -+ if (!document()) { -+ return; -+ } -+ reloadPage(); -+} -+ -+void PageView::slotRotationChanged(int value) -+{ -+ m_rotation = value; -+ if (!document()) { -+ return; -+ } -+ reloadPage(); -+} -+ -+#include "pageview.moc" -diff --git a/qt4/demos/pageview.h b/qt4/demos/pageview.h -new file mode 100644 -index 00000000..24065028 ---- /dev/null -+++ b/qt4/demos/pageview.h -@@ -0,0 +1,53 @@ -+/* -+ * Copyright (C) 2008-2009, Pino Toscano -+ * Copyright (C) 2013, Fabio D'Urso -+ * -+ * 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 PAGEVIEW_H -+#define PAGEVIEW_H -+ -+#include -+ -+#include "documentobserver.h" -+ -+class QLabel; -+ -+class PageView : public QScrollArea, public DocumentObserver -+{ -+ Q_OBJECT -+ -+public: -+ PageView(QWidget *parent = 0); -+ ~PageView(); -+ -+ /*virtual*/ void documentLoaded(); -+ /*virtual*/ void documentClosed(); -+ /*virtual*/ void pageChanged(int page); -+ -+private Q_SLOTS: -+ void slotZoomChanged(qreal value); -+ void slotRotationChanged(int value); -+ -+private: -+ QLabel *m_imageLabel; -+ qreal m_zoom; -+ int m_rotation; -+ int m_dpiX; -+ int m_dpiY; -+}; -+ -+#endif -diff --git a/qt4/demos/permissions.cpp b/qt4/demos/permissions.cpp -new file mode 100644 -index 00000000..38205b2e ---- /dev/null -+++ b/qt4/demos/permissions.cpp -@@ -0,0 +1,66 @@ -+/* -+ * Copyright (C) 2008-2009, Pino Toscano -+ * -+ * 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 "permissions.h" -+ -+#include -+ -+#include -+ -+PermissionsDock::PermissionsDock(QWidget *parent) -+ : AbstractInfoDock(parent) -+{ -+ m_table = new QListWidget(this); -+ setWidget(m_table); -+ setWindowTitle(tr("Permissions")); -+ m_table->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); -+} -+ -+PermissionsDock::~PermissionsDock() -+{ -+} -+ -+void PermissionsDock::fillInfo() -+{ -+#define ADD_ROW(title, function) \ -+do { \ -+ QListWidgetItem *item = new QListWidgetItem(); \ -+ item->setFlags(item->flags() & ~Qt::ItemIsEnabled); \ -+ item->setText(title); \ -+ item->setCheckState(document()->function() ? Qt::Checked : Qt::Unchecked); \ -+ m_table->addItem(item); \ -+} while (0) -+ ADD_ROW("Print", okToPrint); -+ ADD_ROW("PrintHiRes", okToPrintHighRes); -+ ADD_ROW("Change", okToChange); -+ ADD_ROW("Copy", okToCopy); -+ ADD_ROW("Add Notes", okToAddNotes); -+ ADD_ROW("Fill Forms", okToFillForm); -+ ADD_ROW("Create Forms", okToCreateFormFields); -+ ADD_ROW("Extract for accessibility", okToExtractForAccessibility); -+ ADD_ROW("Assemble", okToAssemble); -+#undef ADD_ROW -+} -+ -+void PermissionsDock::documentClosed() -+{ -+ m_table->clear(); -+ AbstractInfoDock::documentClosed(); -+} -+ -+#include "permissions.moc" -diff --git a/qt4/demos/permissions.h b/qt4/demos/permissions.h -new file mode 100644 -index 00000000..13bcbbf0 ---- /dev/null -+++ b/qt4/demos/permissions.h -@@ -0,0 +1,43 @@ -+/* -+ * Copyright (C) 2008-2009, Pino Toscano -+ * -+ * 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 PERMISSIONS_H -+#define PERMISSIONS_H -+ -+#include "abstractinfodock.h" -+ -+class QListWidget; -+ -+class PermissionsDock : public AbstractInfoDock -+{ -+ Q_OBJECT -+ -+public: -+ PermissionsDock(QWidget *parent = 0); -+ ~PermissionsDock(); -+ -+ /*virtual*/ void documentClosed(); -+ -+protected: -+ /*virtual*/ void fillInfo(); -+ -+private: -+ QListWidget *m_table; -+}; -+ -+#endif -diff --git a/qt4/demos/thumbnails.cpp b/qt4/demos/thumbnails.cpp -new file mode 100644 -index 00000000..07b19ca7 ---- /dev/null -+++ b/qt4/demos/thumbnails.cpp -@@ -0,0 +1,84 @@ -+/* -+ * Copyright (C) 2009, Shawn Rutledge -+ * Copyright (C) 2009, Pino Toscano -+ * -+ * 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 "thumbnails.h" -+ -+#include -+ -+#include -+ -+static const int PageRole = Qt::UserRole + 1; -+ -+ThumbnailsDock::ThumbnailsDock(QWidget *parent) -+ : AbstractInfoDock(parent) -+{ -+ m_list = new QListWidget(this); -+ setWidget(m_list); -+ setWindowTitle(tr("Thumbnails")); -+ m_list->setViewMode(QListView::ListMode); -+ m_list->setMovement(QListView::Static); -+ m_list->setVerticalScrollMode(QListView::ScrollPerPixel); -+ connect(m_list, SIGNAL(itemActivated(QListWidgetItem*)), -+ this, SLOT(slotItemActivated(QListWidgetItem*))); -+} -+ -+ThumbnailsDock::~ThumbnailsDock() -+{ -+} -+ -+void ThumbnailsDock::fillInfo() -+{ -+ const int num = document()->numPages(); -+ QSize maxSize; -+ for (int i = 0; i < num; ++i) { -+ const Poppler::Page *page = document()->page(i); -+ const QImage image = page->thumbnail(); -+ if (!image.isNull()) { -+ QListWidgetItem *item = new QListWidgetItem(); -+ item->setText(QString::number(i + 1)); -+ item->setData(Qt::DecorationRole, QPixmap::fromImage(image)); -+ item->setData(PageRole, i); -+ m_list->addItem(item); -+ maxSize.setWidth(qMax(maxSize.width(), image.width())); -+ maxSize.setHeight(qMax(maxSize.height(), image.height())); -+ } -+ delete page; -+ } -+ if (num > 0) { -+ m_list->setGridSize(maxSize); -+ m_list->setIconSize(maxSize); -+ } -+} -+ -+void ThumbnailsDock::documentClosed() -+{ -+ m_list->clear(); -+ AbstractInfoDock::documentClosed(); -+} -+ -+void ThumbnailsDock::slotItemActivated(QListWidgetItem *item) -+{ -+ if (!item) { -+ return; -+ } -+ -+ setPage(item->data(PageRole).toInt()); -+} -+ -+#include "thumbnails.moc" -diff --git a/qt4/demos/thumbnails.h b/qt4/demos/thumbnails.h -new file mode 100644 -index 00000000..076d5aee ---- /dev/null -+++ b/qt4/demos/thumbnails.h -@@ -0,0 +1,48 @@ -+/* -+ * Copyright (C) 2009, Shawn Rutledge -+ * Copyright (C) 2009, Pino Toscano -+ * -+ * 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 THUMBNAILS_H -+#define THUMBNAILS_H -+ -+#include "abstractinfodock.h" -+ -+class QListWidget; -+class QListWidgetItem; -+ -+class ThumbnailsDock : public AbstractInfoDock -+{ -+ Q_OBJECT -+ -+public: -+ ThumbnailsDock(QWidget *parent = 0); -+ ~ThumbnailsDock(); -+ -+ /*virtual*/ void documentClosed(); -+ -+protected: -+ /*virtual*/ void fillInfo(); -+ -+private Q_SLOTS: -+ void slotItemActivated(QListWidgetItem *item); -+ -+private: -+ QListWidget *m_list; -+}; -+ -+#endif -diff --git a/qt4/demos/toc.cpp b/qt4/demos/toc.cpp -new file mode 100644 -index 00000000..bf3e5cbb ---- /dev/null -+++ b/qt4/demos/toc.cpp -@@ -0,0 +1,88 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 "toc.h" -+ -+#include -+ -+#include -+#include -+ -+static void fillToc(const QDomNode &parent, QTreeWidget *tree, QTreeWidgetItem *parentItem) -+{ -+ QTreeWidgetItem *newitem = 0; -+ for (QDomNode node = parent.firstChild(); !node.isNull(); node = node.nextSibling()) { -+ QDomElement e = node.toElement(); -+ -+ if (!parentItem) { -+ newitem = new QTreeWidgetItem(tree, newitem); -+ } else { -+ newitem = new QTreeWidgetItem(parentItem, newitem); -+ } -+ newitem->setText(0, e.tagName()); -+ -+ bool isOpen = false; -+ if (e.hasAttribute(QString::fromLatin1("Open"))) { -+ isOpen = QVariant(e.attribute(QString::fromLatin1("Open"))).toBool(); -+ } -+ if (isOpen) { -+ tree->expandItem(newitem); -+ } -+ -+ if (e.hasChildNodes()) { -+ fillToc(node, tree, newitem); -+ } -+ } -+} -+ -+ -+TocDock::TocDock(QWidget *parent) -+ : AbstractInfoDock(parent) -+{ -+ m_tree = new QTreeWidget(this); -+ setWidget(m_tree); -+ m_tree->setAlternatingRowColors(true); -+ m_tree->header()->hide(); -+ setWindowTitle(tr("TOC")); -+ m_tree->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); -+} -+ -+TocDock::~TocDock() -+{ -+} -+ -+void TocDock::fillInfo() -+{ -+ const QDomDocument *toc = document()->toc(); -+ if (toc) { -+ fillToc(*toc, m_tree, 0); -+ } else { -+ QTreeWidgetItem *item = new QTreeWidgetItem(); -+ item->setText(0, tr("No TOC")); -+ item->setFlags(item->flags() & ~Qt::ItemIsEnabled); -+ m_tree->addTopLevelItem(item); -+ } -+} -+ -+void TocDock::documentClosed() -+{ -+ m_tree->clear(); -+ AbstractInfoDock::documentClosed(); -+} -+ -+#include "toc.moc" -diff --git a/qt4/demos/toc.h b/qt4/demos/toc.h -new file mode 100644 -index 00000000..bbc90827 ---- /dev/null -+++ b/qt4/demos/toc.h -@@ -0,0 +1,43 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 TOC_H -+#define TOC_H -+ -+#include "abstractinfodock.h" -+ -+class QTreeWidget; -+ -+class TocDock : public AbstractInfoDock -+{ -+ Q_OBJECT -+ -+public: -+ TocDock(QWidget *parent = 0); -+ ~TocDock(); -+ -+ /*virtual*/ void documentClosed(); -+ -+protected: -+ /*virtual*/ void fillInfo(); -+ -+private: -+ QTreeWidget *m_tree; -+}; -+ -+#endif -diff --git a/qt4/demos/viewer.cpp b/qt4/demos/viewer.cpp -new file mode 100644 -index 00000000..c34af23f ---- /dev/null -+++ b/qt4/demos/viewer.cpp -@@ -0,0 +1,319 @@ -+/* -+ * Copyright (C) 2008-2009, Pino Toscano -+ * Copyright (C) 2008, Albert Astals Cid -+ * Copyright (C) 2009, Shawn Rutledge -+ * Copyright (C) 2013, Fabio D'Urso -+ * -+ * 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 "viewer.h" -+ -+#include "embeddedfiles.h" -+#include "fonts.h" -+#include "info.h" -+#include "metadata.h" -+#include "navigationtoolbar.h" -+#include "optcontent.h" -+#include "pageview.h" -+#include "permissions.h" -+#include "thumbnails.h" -+#include "toc.h" -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+PdfViewer::PdfViewer() -+ : QMainWindow(), m_currentPage(0), m_doc(0) -+{ -+ setWindowTitle(tr("Poppler-Qt4 Demo")); -+ -+ // setup the menus -+ QMenu *fileMenu = menuBar()->addMenu(tr("&File")); -+ m_fileOpenAct = fileMenu->addAction(tr("&Open"), this, SLOT(slotOpenFile())); -+ m_fileOpenAct->setShortcut(Qt::CTRL + Qt::Key_O); -+ fileMenu->addSeparator(); -+ m_fileSaveCopyAct = fileMenu->addAction(tr("&Save a Copy..."), this, SLOT(slotSaveCopy())); -+ m_fileSaveCopyAct->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_S); -+ m_fileSaveCopyAct->setEnabled(false); -+ fileMenu->addSeparator(); -+ QAction *act = fileMenu->addAction(tr("&Quit"), qApp, SLOT(closeAllWindows())); -+ act->setShortcut(Qt::CTRL + Qt::Key_Q); -+ -+ QMenu *viewMenu = menuBar()->addMenu(tr("&View")); -+ -+ QMenu *settingsMenu = menuBar()->addMenu(tr("&Settings")); -+ m_settingsTextAAAct = settingsMenu->addAction(tr("Text Antialias")); -+ m_settingsTextAAAct->setCheckable(true); -+ connect(m_settingsTextAAAct, SIGNAL(toggled(bool)), this, SLOT(slotToggleTextAA(bool))); -+ m_settingsGfxAAAct = settingsMenu->addAction(tr("Graphics Antialias")); -+ m_settingsGfxAAAct->setCheckable(true); -+ connect(m_settingsGfxAAAct, SIGNAL(toggled(bool)), this, SLOT(slotToggleGfxAA(bool))); -+ QMenu *settingsRenderMenu = settingsMenu->addMenu(tr("Render Backend")); -+ m_settingsRenderBackendGrp = new QActionGroup(settingsRenderMenu); -+ m_settingsRenderBackendGrp->setExclusive(true); -+ act = settingsRenderMenu->addAction(tr("Splash")); -+ act->setCheckable(true); -+ act->setChecked(true); -+ act->setData(qVariantFromValue(0)); -+ m_settingsRenderBackendGrp->addAction(act); -+ act = settingsRenderMenu->addAction(tr("Arthur")); -+ act->setCheckable(true); -+ act->setData(qVariantFromValue(1)); -+ m_settingsRenderBackendGrp->addAction(act); -+ connect(m_settingsRenderBackendGrp, SIGNAL(triggered(QAction*)), -+ this, SLOT(slotRenderBackend(QAction*))); -+ -+ QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); -+ act = helpMenu->addAction(tr("&About"), this, SLOT(slotAbout())); -+ act = helpMenu->addAction(tr("About &Qt"), this, SLOT(slotAboutQt())); -+ -+ NavigationToolBar *navbar = new NavigationToolBar(this); -+ addToolBar(navbar); -+ m_observers.append(navbar); -+ -+ PageView *view = new PageView(this); -+ setCentralWidget(view); -+ m_observers.append(view); -+ -+ InfoDock *infoDock = new InfoDock(this); -+ addDockWidget(Qt::LeftDockWidgetArea, infoDock); -+ infoDock->hide(); -+ viewMenu->addAction(infoDock->toggleViewAction()); -+ m_observers.append(infoDock); -+ -+ TocDock *tocDock = new TocDock(this); -+ addDockWidget(Qt::LeftDockWidgetArea, tocDock); -+ tocDock->hide(); -+ viewMenu->addAction(tocDock->toggleViewAction()); -+ m_observers.append(tocDock); -+ -+ FontsDock *fontsDock = new FontsDock(this); -+ addDockWidget(Qt::LeftDockWidgetArea, fontsDock); -+ fontsDock->hide(); -+ viewMenu->addAction(fontsDock->toggleViewAction()); -+ m_observers.append(fontsDock); -+ -+ PermissionsDock *permissionsDock = new PermissionsDock(this); -+ addDockWidget(Qt::LeftDockWidgetArea, permissionsDock); -+ permissionsDock->hide(); -+ viewMenu->addAction(permissionsDock->toggleViewAction()); -+ m_observers.append(permissionsDock); -+ -+ ThumbnailsDock *thumbnailsDock = new ThumbnailsDock(this); -+ addDockWidget(Qt::LeftDockWidgetArea, thumbnailsDock); -+ thumbnailsDock->hide(); -+ viewMenu->addAction(thumbnailsDock->toggleViewAction()); -+ m_observers.append(thumbnailsDock); -+ -+ EmbeddedFilesDock *embfilesDock = new EmbeddedFilesDock(this); -+ addDockWidget(Qt::BottomDockWidgetArea, embfilesDock); -+ embfilesDock->hide(); -+ viewMenu->addAction(embfilesDock->toggleViewAction()); -+ m_observers.append(embfilesDock); -+ -+ MetadataDock *metadataDock = new MetadataDock(this); -+ addDockWidget(Qt::BottomDockWidgetArea, metadataDock); -+ metadataDock->hide(); -+ viewMenu->addAction(metadataDock->toggleViewAction()); -+ m_observers.append(metadataDock); -+ -+ OptContentDock *optContentDock = new OptContentDock(this); -+ addDockWidget(Qt::LeftDockWidgetArea, optContentDock); -+ optContentDock->hide(); -+ viewMenu->addAction(optContentDock->toggleViewAction()); -+ m_observers.append(optContentDock); -+ -+ Q_FOREACH(DocumentObserver *obs, m_observers) { -+ obs->m_viewer = this; -+ } -+ -+ connect(navbar, SIGNAL(zoomChanged(qreal)), view, SLOT(slotZoomChanged(qreal))); -+ connect(navbar, SIGNAL(rotationChanged(int)), view, SLOT(slotRotationChanged(int))); -+ -+ // activate AA by default -+ m_settingsTextAAAct->setChecked(true); -+ m_settingsGfxAAAct->setChecked(true); -+} -+ -+PdfViewer::~PdfViewer() -+{ -+ closeDocument(); -+} -+ -+QSize PdfViewer::sizeHint() const -+{ -+ return QSize(500, 600); -+} -+ -+void PdfViewer::loadDocument(const QString &file) -+{ -+ Poppler::Document *newdoc = Poppler::Document::load(file); -+ if (!newdoc) { -+ QMessageBox msgbox(QMessageBox::Critical, tr("Open Error"), tr("Cannot open:\n") + file, -+ QMessageBox::Ok, this); -+ msgbox.exec(); -+ return; -+ } -+ -+ while (newdoc->isLocked()) { -+ bool ok = true; -+ QString password = QInputDialog::getText(this, tr("Document Password"), -+ tr("Please insert the password of the document:"), -+ QLineEdit::Password, QString(), &ok); -+ if (!ok) { -+ delete newdoc; -+ return; -+ } -+ newdoc->unlock(password.toLatin1(), password.toLatin1()); -+ } -+ -+ closeDocument(); -+ -+ m_doc = newdoc; -+ -+ m_doc->setRenderHint(Poppler::Document::TextAntialiasing, m_settingsTextAAAct->isChecked()); -+ m_doc->setRenderHint(Poppler::Document::Antialiasing, m_settingsGfxAAAct->isChecked()); -+ m_doc->setRenderBackend((Poppler::Document::RenderBackend)m_settingsRenderBackendGrp->checkedAction()->data().toInt()); -+ -+ Q_FOREACH(DocumentObserver *obs, m_observers) { -+ obs->documentLoaded(); -+ obs->pageChanged(0); -+ } -+ -+ m_fileSaveCopyAct->setEnabled(true); -+} -+ -+void PdfViewer::closeDocument() -+{ -+ if (!m_doc) { -+ return; -+ } -+ -+ Q_FOREACH(DocumentObserver *obs, m_observers) { -+ obs->documentClosed(); -+ } -+ -+ m_currentPage = 0; -+ delete m_doc; -+ m_doc = 0; -+ -+ m_fileSaveCopyAct->setEnabled(false); -+} -+ -+void PdfViewer::slotOpenFile() -+{ -+ QString fileName = QFileDialog::getOpenFileName(this, tr("Open PDF Document"), QDir::homePath(), tr("PDF Documents (*.pdf)")); -+ if (fileName.isEmpty()) { -+ return; -+ } -+ -+ loadDocument(fileName); -+} -+ -+void PdfViewer::slotSaveCopy() -+{ -+ if (!m_doc) { -+ return; -+ } -+ -+ QString fileName = QFileDialog::getSaveFileName(this, tr("Save Copy"), QDir::homePath(), tr("PDF Documents (*.pdf)")); -+ if (fileName.isEmpty()) { -+ return; -+ } -+ -+ Poppler::PDFConverter *converter = m_doc->pdfConverter(); -+ converter->setOutputFileName(fileName); -+ converter->setPDFOptions(converter->pdfOptions() & ~Poppler::PDFConverter::WithChanges); -+ if (!converter->convert()) { -+ QMessageBox msgbox(QMessageBox::Critical, tr("Save Error"), tr("Cannot export to:\n%1").arg(fileName), -+ QMessageBox::Ok, this); -+ } -+ delete converter; -+} -+ -+void PdfViewer::slotAbout() -+{ -+ const QString text("This is a demo of the Poppler-Qt4 library."); -+ QMessageBox::about(this, QString::fromLatin1("About Poppler-Qt4 Demo"), text); -+} -+ -+void PdfViewer::slotAboutQt() -+{ -+ QMessageBox::aboutQt(this); -+} -+ -+void PdfViewer::slotToggleTextAA(bool value) -+{ -+ if (!m_doc) { -+ return; -+ } -+ -+ m_doc->setRenderHint(Poppler::Document::TextAntialiasing, value); -+ -+ Q_FOREACH(DocumentObserver *obs, m_observers) { -+ obs->pageChanged(m_currentPage); -+ } -+} -+ -+void PdfViewer::slotToggleGfxAA(bool value) -+{ -+ if (!m_doc) { -+ return; -+ } -+ -+ m_doc->setRenderHint(Poppler::Document::Antialiasing, value); -+ -+ Q_FOREACH(DocumentObserver *obs, m_observers) { -+ obs->pageChanged(m_currentPage); -+ } -+} -+ -+void PdfViewer::slotRenderBackend(QAction *act) -+{ -+ if (!m_doc || !act) { -+ return; -+ } -+ -+ m_doc->setRenderBackend((Poppler::Document::RenderBackend)act->data().toInt()); -+ -+ Q_FOREACH(DocumentObserver *obs, m_observers) { -+ obs->pageChanged(m_currentPage); -+ } -+} -+ -+void PdfViewer::setPage(int page) -+{ -+ Q_FOREACH(DocumentObserver *obs, m_observers) { -+ obs->pageChanged(page); -+ } -+ -+ m_currentPage = page; -+} -+ -+int PdfViewer::page() const -+{ -+ return m_currentPage; -+} -+ -+#include "viewer.moc" -diff --git a/qt4/demos/viewer.h b/qt4/demos/viewer.h -new file mode 100644 -index 00000000..5e0eaaff ---- /dev/null -+++ b/qt4/demos/viewer.h -@@ -0,0 +1,73 @@ -+/* -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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 PDFVIEWER_H -+#define PDFVIEWER_H -+ -+#include -+ -+class QAction; -+class QActionGroup; -+class QLabel; -+class DocumentObserver; -+namespace Poppler { -+class Document; -+} -+ -+class PdfViewer : public QMainWindow -+{ -+ Q_OBJECT -+ -+ friend class DocumentObserver; -+ -+public: -+ PdfViewer(); -+ ~PdfViewer(); -+ -+ /*virtual*/ QSize sizeHint() const; -+ -+ void loadDocument(const QString &file); -+ void closeDocument(); -+ -+private Q_SLOTS: -+ void slotOpenFile(); -+ void slotSaveCopy(); -+ void slotAbout(); -+ void slotAboutQt(); -+ void slotToggleTextAA(bool value); -+ void slotToggleGfxAA(bool value); -+ void slotRenderBackend(QAction *act); -+ -+private: -+ void setPage(int page); -+ int page() const; -+ -+ int m_currentPage; -+ -+ QAction *m_fileOpenAct; -+ QAction *m_fileSaveCopyAct; -+ QAction *m_settingsTextAAAct; -+ QAction *m_settingsGfxAAAct; -+ QActionGroup *m_settingsRenderBackendGrp; -+ -+ QList m_observers; -+ -+ Poppler::Document *m_doc; -+}; -+ -+#endif -diff --git a/qt4/src/.gitignore b/qt4/src/.gitignore -new file mode 100644 -index 00000000..3d124ddd ---- /dev/null -+++ b/qt4/src/.gitignore -@@ -0,0 +1,9 @@ -+.deps -+.libs -+*.la -+*.lo -+Makefile -+Makefile.in -+APIDOCS-html -+APIDOCS-latex -+*.moc -diff --git a/qt4/src/ArthurOutputDev.cc b/qt4/src/ArthurOutputDev.cc -new file mode 100644 -index 00000000..f2fa6f17 ---- /dev/null -+++ b/qt4/src/ArthurOutputDev.cc -@@ -0,0 +1,817 @@ -+//======================================================================== -+// -+// ArthurOutputDev.cc -+// -+// Copyright 2003 Glyph & Cog, LLC -+// -+//======================================================================== -+ -+//======================================================================== -+// -+// Modified under the Poppler project - http://poppler.freedesktop.org -+// -+// All changes made under the Poppler project to this file are licensed -+// under GPL version 2 or later -+// -+// Copyright (C) 2005 Brad Hards -+// Copyright (C) 2005-2009, 2011, 2012, 2014, 2015 Albert Astals Cid -+// Copyright (C) 2008, 2010 Pino Toscano -+// Copyright (C) 2009, 2011 Carlos Garcia Campos -+// Copyright (C) 2009 Petr Gajdos -+// Copyright (C) 2010 Matthias Fauconneau -+// Copyright (C) 2011 Andreas Hartmetz -+// Copyright (C) 2013 Thomas Freitag -+// Copyright (C) 2013 Dominik Haumann -+// Copyright (C) 2017 Adrian Johnson -+// -+// To see a description of the changes please see the Changelog file that -+// came with your tarball or type make ChangeLog if you are building from git -+// -+//======================================================================== -+ -+#include -+ -+#ifdef USE_GCC_PRAGMAS -+#pragma implementation -+#endif -+ -+#include -+#include -+ -+#include "goo/gfile.h" -+#include "GlobalParams.h" -+#include "Error.h" -+#include "Object.h" -+#include "GfxState.h" -+#include "GfxFont.h" -+#include "Link.h" -+#include "FontEncodingTables.h" -+#include -+#include "ArthurOutputDev.h" -+ -+#include -+#include -+//------------------------------------------------------------------------ -+ -+#ifdef HAVE_SPLASH -+#include "splash/SplashFontFileID.h" -+#include "splash/SplashFontFile.h" -+#include "splash/SplashFontEngine.h" -+#include "splash/SplashFont.h" -+#include "splash/SplashMath.h" -+#include "splash/SplashPath.h" -+#include "splash/SplashGlyphBitmap.h" -+//------------------------------------------------------------------------ -+// SplashOutFontFileID -+//------------------------------------------------------------------------ -+ -+class SplashOutFontFileID: public SplashFontFileID { -+public: -+ -+ SplashOutFontFileID(const Ref *rA) { r = *rA; } -+ -+ ~SplashOutFontFileID() {} -+ -+ bool matches(SplashFontFileID *id) { -+ return ((SplashOutFontFileID *)id)->r.num == r.num && -+ ((SplashOutFontFileID *)id)->r.gen == r.gen; -+ } -+ -+private: -+ -+ Ref r; -+}; -+ -+#endif -+ -+//------------------------------------------------------------------------ -+// ArthurOutputDev -+//------------------------------------------------------------------------ -+ -+ArthurOutputDev::ArthurOutputDev(QPainter *painter): -+ m_painter(painter), -+ m_fontHinting(NoHinting) -+{ -+ m_currentBrush = QBrush(Qt::SolidPattern); -+ m_fontEngine = 0; -+ m_font = 0; -+} -+ -+ArthurOutputDev::~ArthurOutputDev() -+{ -+#ifdef HAVE_SPLASH -+ delete m_fontEngine; -+#endif -+} -+ -+void ArthurOutputDev::startDoc(XRef *xrefA) { -+ xref = xrefA; -+#ifdef HAVE_SPLASH -+ delete m_fontEngine; -+ -+ const bool isHintingEnabled = m_fontHinting != NoHinting; -+ const bool isSlightHinting = m_fontHinting == SlightHinting; -+ -+ m_fontEngine = new SplashFontEngine( -+ true, // I just set this to true. We should finally remove the QT4. -+ isHintingEnabled, -+ isSlightHinting, -+ m_painter->testRenderHint(QPainter::TextAntialiasing)); -+#endif -+} -+ -+void ArthurOutputDev::startPage(int pageNum, GfxState *state, XRef *xref) -+{ -+ // fill page with white background. -+ int w = static_cast(state->getPageWidth()); -+ int h = static_cast(state->getPageHeight()); -+ QColor fillColour(Qt::white); -+ QBrush fill(fillColour); -+ m_painter->save(); -+ m_painter->setPen(fillColour); -+ m_painter->setBrush(fill); -+ m_painter->drawRect(0, 0, w, h); -+ m_painter->restore(); -+} -+ -+void ArthurOutputDev::endPage() { -+} -+ -+void ArthurOutputDev::saveState(GfxState *state) -+{ -+ m_painter->save(); -+} -+ -+void ArthurOutputDev::restoreState(GfxState *state) -+{ -+ m_painter->restore(); -+} -+ -+void ArthurOutputDev::updateAll(GfxState *state) -+{ -+ OutputDev::updateAll(state); -+ m_needFontUpdate = true; -+} -+ -+// This looks wrong - why aren't adjusting the matrix? -+void ArthurOutputDev::updateCTM(GfxState *state, double m11, double m12, -+ double m21, double m22, -+ double m31, double m32) -+{ -+ updateLineDash(state); -+ updateLineJoin(state); -+ updateLineCap(state); -+ updateLineWidth(state); -+} -+ -+void ArthurOutputDev::updateLineDash(GfxState *state) -+{ -+ double *dashPattern; -+ int dashLength; -+ double dashStart; -+ state->getLineDash(&dashPattern, &dashLength, &dashStart); -+ QVector pattern(dashLength); -+ for (int i = 0; i < dashLength; ++i) { -+ pattern[i] = dashPattern[i]; -+ } -+ m_currentPen.setDashPattern(pattern); -+ m_currentPen.setDashOffset(dashStart); -+ m_painter->setPen(m_currentPen); -+} -+ -+void ArthurOutputDev::updateFlatness(GfxState *state) -+{ -+ // qDebug() << "updateFlatness"; -+} -+ -+void ArthurOutputDev::updateLineJoin(GfxState *state) -+{ -+ switch (state->getLineJoin()) { -+ case 0: -+ m_currentPen.setJoinStyle(Qt::MiterJoin); -+ break; -+ case 1: -+ m_currentPen.setJoinStyle(Qt::RoundJoin); -+ break; -+ case 2: -+ m_currentPen.setJoinStyle(Qt::BevelJoin); -+ break; -+ } -+ m_painter->setPen(m_currentPen); -+} -+ -+void ArthurOutputDev::updateLineCap(GfxState *state) -+{ -+ switch (state->getLineCap()) { -+ case 0: -+ m_currentPen.setCapStyle(Qt::FlatCap); -+ break; -+ case 1: -+ m_currentPen.setCapStyle(Qt::RoundCap); -+ break; -+ case 2: -+ m_currentPen.setCapStyle(Qt::SquareCap); -+ break; -+ } -+ m_painter->setPen(m_currentPen); -+} -+ -+void ArthurOutputDev::updateMiterLimit(GfxState *state) -+{ -+ m_currentPen.setMiterLimit(state->getMiterLimit()); -+ m_painter->setPen(m_currentPen); -+} -+ -+void ArthurOutputDev::updateLineWidth(GfxState *state) -+{ -+ m_currentPen.setWidthF(state->getLineWidth()); -+ m_painter->setPen(m_currentPen); -+} -+ -+void ArthurOutputDev::updateFillColor(GfxState *state) -+{ -+ GfxRGB rgb; -+ QColor brushColour = m_currentBrush.color(); -+ state->getFillRGB(&rgb); -+ brushColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), brushColour.alphaF()); -+ m_currentBrush.setColor(brushColour); -+} -+ -+void ArthurOutputDev::updateStrokeColor(GfxState *state) -+{ -+ GfxRGB rgb; -+ QColor penColour = m_currentPen.color(); -+ state->getStrokeRGB(&rgb); -+ penColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), penColour.alphaF()); -+ m_currentPen.setColor(penColour); -+ m_painter->setPen(m_currentPen); -+} -+ -+void ArthurOutputDev::updateFillOpacity(GfxState *state) -+{ -+ QColor brushColour= m_currentBrush.color(); -+ brushColour.setAlphaF(state->getFillOpacity()); -+ m_currentBrush.setColor(brushColour); -+} -+ -+void ArthurOutputDev::updateStrokeOpacity(GfxState *state) -+{ -+ QColor penColour= m_currentPen.color(); -+ penColour.setAlphaF(state->getStrokeOpacity()); -+ m_currentPen.setColor(penColour); -+ m_painter->setPen(m_currentPen); -+} -+ -+void ArthurOutputDev::updateFont(GfxState *state) -+{ -+#ifdef HAVE_SPLASH -+ GfxFont *gfxFont; -+ GfxFontLoc *fontLoc; -+ GfxFontType fontType; -+ SplashOutFontFileID *id; -+ SplashFontFile *fontFile; -+ SplashFontSrc *fontsrc = NULL; -+ FoFiTrueType *ff; -+ Object refObj, strObj; -+ GooString *fileName; -+ char *tmpBuf; -+ int tmpBufLen = 0; -+ int *codeToGID; -+ const double *textMat; -+ double m11, m12, m21, m22, fontSize; -+ SplashCoord mat[4]; -+ int n; -+ int faceIndex = 0; -+ SplashCoord matrix[6]; -+ -+ m_needFontUpdate = false; -+ m_font = NULL; -+ fileName = NULL; -+ tmpBuf = NULL; -+ fontLoc = NULL; -+ -+ if (!(gfxFont = state->getFont())) { -+ goto err1; -+ } -+ fontType = gfxFont->getType(); -+ if (fontType == fontType3) { -+ goto err1; -+ } -+ -+ // check the font file cache -+ id = new SplashOutFontFileID(gfxFont->getID()); -+ if ((fontFile = m_fontEngine->getFontFile(id))) { -+ delete id; -+ -+ } else { -+ -+ if (!(fontLoc = gfxFont->locateFont(xref, NULL))) { -+ error(errSyntaxError, -1, "Couldn't find a font for '{0:s}'", -+ gfxFont->getName() ? gfxFont->getName()->c_str() -+ : "(unnamed)"); -+ goto err2; -+ } -+ -+ // embedded font -+ if (fontLoc->locType == gfxFontLocEmbedded) { -+ // if there is an embedded font, read it to memory -+ tmpBuf = gfxFont->readEmbFontFile(xref, &tmpBufLen); -+ if (! tmpBuf) -+ goto err2; -+ -+ // external font -+ } else { // gfxFontLocExternal -+ fileName = fontLoc->path; -+ fontType = fontLoc->fontType; -+ } -+ -+ fontsrc = new SplashFontSrc; -+ if (fileName) -+ fontsrc->setFile(fileName, false); -+ else -+ fontsrc->setBuf(tmpBuf, tmpBufLen, true); -+ -+ // load the font file -+ switch (fontType) { -+ case fontType1: -+ if (!(fontFile = m_fontEngine->loadType1Font( -+ id, -+ fontsrc, -+ (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) { -+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", -+ gfxFont->getName() ? gfxFont->getName()->c_str() -+ : "(unnamed)"); -+ goto err2; -+ } -+ break; -+ case fontType1C: -+ if (!(fontFile = m_fontEngine->loadType1CFont( -+ id, -+ fontsrc, -+ (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) { -+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", -+ gfxFont->getName() ? gfxFont->getName()->c_str() -+ : "(unnamed)"); -+ goto err2; -+ } -+ break; -+ case fontType1COT: -+ if (!(fontFile = m_fontEngine->loadOpenTypeT1CFont( -+ id, -+ fontsrc, -+ (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) { -+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", -+ gfxFont->getName() ? gfxFont->getName()->c_str() -+ : "(unnamed)"); -+ goto err2; -+ } -+ break; -+ case fontTrueType: -+ case fontTrueTypeOT: -+ if (fileName) -+ ff = FoFiTrueType::load(fileName->c_str()); -+ else -+ ff = FoFiTrueType::make(tmpBuf, tmpBufLen); -+ if (ff) { -+ codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff); -+ n = 256; -+ delete ff; -+ } else { -+ codeToGID = NULL; -+ n = 0; -+ } -+ if (!(fontFile = m_fontEngine->loadTrueTypeFont( -+ id, -+ fontsrc, -+ codeToGID, n))) { -+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", -+ gfxFont->getName() ? gfxFont->getName()->c_str() -+ : "(unnamed)"); -+ goto err2; -+ } -+ break; -+ case fontCIDType0: -+ case fontCIDType0C: -+ if (!(fontFile = m_fontEngine->loadCIDFont( -+ id, -+ fontsrc))) { -+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", -+ gfxFont->getName() ? gfxFont->getName()->c_str() -+ : "(unnamed)"); -+ goto err2; -+ } -+ break; -+ case fontCIDType0COT: -+ if (((GfxCIDFont *)gfxFont)->getCIDToGID()) { -+ n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen(); -+ codeToGID = (int *)gmallocn(n, sizeof(int)); -+ memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(), -+ n * sizeof(int)); -+ } else { -+ codeToGID = NULL; -+ n = 0; -+ } -+ if (!(fontFile = m_fontEngine->loadOpenTypeCFFFont( -+ id, -+ fontsrc, -+ codeToGID, n))) { -+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", -+ gfxFont->getName() ? gfxFont->getName()->c_str() -+ : "(unnamed)"); -+ goto err2; -+ } -+ break; -+ case fontCIDType2: -+ case fontCIDType2OT: -+ codeToGID = NULL; -+ n = 0; -+ if (((GfxCIDFont *)gfxFont)->getCIDToGID()) { -+ n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen(); -+ if (n) { -+ codeToGID = (int *)gmallocn(n, sizeof(int)); -+ memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(), -+ n * sizeof(int)); -+ } -+ } else { -+ if (fileName) -+ ff = FoFiTrueType::load(fileName->c_str()); -+ else -+ ff = FoFiTrueType::make(tmpBuf, tmpBufLen); -+ if (! ff) -+ goto err2; -+ codeToGID = ((GfxCIDFont *)gfxFont)->getCodeToGIDMap(ff, &n); -+ delete ff; -+ } -+ if (!(fontFile = m_fontEngine->loadTrueTypeFont( -+ id, -+ fontsrc, -+ codeToGID, n, faceIndex))) { -+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", -+ gfxFont->getName() ? gfxFont->getName()->c_str() -+ : "(unnamed)"); -+ goto err2; -+ } -+ break; -+ default: -+ // this shouldn't happen -+ goto err2; -+ } -+ } -+ -+ // get the font matrix -+ textMat = state->getTextMat(); -+ fontSize = state->getFontSize(); -+ m11 = textMat[0] * fontSize * state->getHorizScaling(); -+ m12 = textMat[1] * fontSize * state->getHorizScaling(); -+ m21 = textMat[2] * fontSize; -+ m22 = textMat[3] * fontSize; -+ -+ { -+ QMatrix painterMatrix = m_painter->worldMatrix(); -+ matrix[0] = painterMatrix.m11(); -+ matrix[1] = painterMatrix.m12(); -+ matrix[2] = painterMatrix.m21(); -+ matrix[3] = painterMatrix.m22(); -+ matrix[4] = painterMatrix.dx(); -+ matrix[5] = painterMatrix.dy(); -+ } -+ -+ // create the scaled font -+ mat[0] = m11; mat[1] = -m12; -+ mat[2] = m21; mat[3] = -m22; -+ m_font = m_fontEngine->getFont(fontFile, mat, matrix); -+ -+ delete fontLoc; -+ if (fontsrc && !fontsrc->isFile) -+ fontsrc->unref(); -+ return; -+ -+ err2: -+ delete id; -+ delete fontLoc; -+ err1: -+ if (fontsrc && !fontsrc->isFile) -+ fontsrc->unref(); -+ return; -+#endif -+} -+ -+static QPainterPath convertPath(GfxState *state, const GfxPath *path, Qt::FillRule fillRule) -+{ -+ const GfxSubpath *subpath; -+ double x1, y1, x2, y2, x3, y3; -+ int i, j; -+ -+ QPainterPath qPath; -+ qPath.setFillRule(fillRule); -+ for (i = 0; i < path->getNumSubpaths(); ++i) { -+ subpath = path->getSubpath(i); -+ if (subpath->getNumPoints() > 0) { -+ state->transform(subpath->getX(0), subpath->getY(0), &x1, &y1); -+ qPath.moveTo(x1, y1); -+ j = 1; -+ while (j < subpath->getNumPoints()) { -+ if (subpath->getCurve(j)) { -+ state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1); -+ state->transform(subpath->getX(j+1), subpath->getY(j+1), &x2, &y2); -+ state->transform(subpath->getX(j+2), subpath->getY(j+2), &x3, &y3); -+ qPath.cubicTo( x1, y1, x2, y2, x3, y3); -+ j += 3; -+ } else { -+ state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1); -+ qPath.lineTo(x1, y1); -+ ++j; -+ } -+ } -+ if (subpath->isClosed()) { -+ qPath.closeSubpath(); -+ } -+ } -+ } -+ return qPath; -+} -+ -+void ArthurOutputDev::stroke(GfxState *state) -+{ -+ m_painter->strokePath( convertPath( state, state->getPath(), Qt::OddEvenFill ), m_currentPen ); -+} -+ -+void ArthurOutputDev::fill(GfxState *state) -+{ -+ m_painter->fillPath( convertPath( state, state->getPath(), Qt::WindingFill ), m_currentBrush ); -+} -+ -+void ArthurOutputDev::eoFill(GfxState *state) -+{ -+ m_painter->fillPath( convertPath( state, state->getPath(), Qt::OddEvenFill ), m_currentBrush ); -+} -+ -+void ArthurOutputDev::clip(GfxState *state) -+{ -+ m_painter->setClipPath(convertPath( state, state->getPath(), Qt::WindingFill ) ); -+} -+ -+void ArthurOutputDev::eoClip(GfxState *state) -+{ -+ m_painter->setClipPath(convertPath( state, state->getPath(), Qt::OddEvenFill ) ); -+} -+ -+void ArthurOutputDev::drawChar(GfxState *state, double x, double y, -+ double dx, double dy, -+ double originX, double originY, -+ CharCode code, int nBytes, Unicode *u, int uLen) { -+#ifdef HAVE_SPLASH -+ double x1, y1; -+ double x2, y2; -+ double px, py; -+// SplashPath *path; -+ int render; -+ unsigned char f; -+ -+ if (m_needFontUpdate) { -+ updateFont(state); -+ } -+ if (!m_font) { -+ return; -+ } -+ -+ // check for invisible text -- this is used by Acrobat Capture -+ render = state->getRender(); -+ if (render == 3) { -+ return; -+ } -+ -+ x -= originX; -+ y -= originY; -+ -+ // fill -+ if (!(render & 1)) { -+ SplashPath * fontPath; -+ fontPath = m_font->getGlyphPath(code); -+ if (fontPath) { -+ QPainterPath qPath; -+ qPath.setFillRule(Qt::WindingFill); -+ for (int i = 0; i < fontPath->getLength(); ++i) { -+ // SplashPath.flags: bitwise or allowed -+ fontPath->getPoint(i, &px, &py, &f); -+ if (f & splashPathLast || f & splashPathClosed) { -+ qPath.closeSubpath(); -+ } -+ if (f & splashPathFirst) { -+ state->transform(px+x, -py+y, &x1, &y1); -+ qPath.moveTo(x1,y1); -+ } -+ if (f & splashPathCurve) { -+ state->transform(px+x, -py+y, &x1, &y1); -+ fontPath->getPoint(i+1, &px, &py, &f); -+ state->transform(px+x, -py+y, &x2, &y2); -+ qPath.quadTo(x1,y1,x2,y2); -+ ++i; -+ } -+ // FIXME fix this -+ // else if (fontPath->flags[i] & splashPathArcCW) { -+ // qDebug() << "Need to implement arc"; -+ // } -+ else { -+ fontPath->getPoint(i, &px, &py, &f); -+ state->transform(px+x, -py+y, &x1, &y1); -+ qPath.lineTo(x1,y1); -+ } -+ } -+ GfxRGB rgb; -+ QColor brushColour = m_currentBrush.color(); -+ state->getFillRGB(&rgb); -+ brushColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), state->getFillOpacity()); -+ m_painter->setBrush(brushColour); -+ m_painter->setPen(Qt::NoPen); -+ m_painter->drawPath(qPath); -+ delete fontPath; -+ } -+ } -+ -+ // stroke -+ if ((render & 3) == 1 || (render & 3) == 2) { -+ qDebug() << "no stroke"; -+ /* -+ if ((path = m_font->getGlyphPath(code))) { -+ path->offset((SplashCoord)x1, (SplashCoord)y1); -+ splash->stroke(path); -+ delete path; -+ } -+ */ -+ } -+ -+ // clip -+ if (render & 4) { -+ qDebug() << "no clip"; -+ /* -+ path = m_font->getGlyphPath(code); -+ path->offset((SplashCoord)x1, (SplashCoord)y1); -+ if (textClipPath) { -+ textClipPath->append(path); -+ delete path; -+ } else { -+ textClipPath = path; -+ } -+ */ -+ } -+#endif -+} -+ -+bool ArthurOutputDev::beginType3Char(GfxState *state, double x, double y, -+ double dx, double dy, -+ CharCode code, Unicode *u, int uLen) -+{ -+ return false; -+} -+ -+void ArthurOutputDev::endType3Char(GfxState *state) -+{ -+} -+ -+void ArthurOutputDev::type3D0(GfxState *state, double wx, double wy) -+{ -+} -+ -+void ArthurOutputDev::type3D1(GfxState *state, double wx, double wy, -+ double llx, double lly, double urx, double ury) -+{ -+} -+ -+void ArthurOutputDev::endTextObject(GfxState *state) -+{ -+} -+ -+ -+void ArthurOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, -+ int width, int height, bool invert, -+ bool interpolate, bool inlineImg) -+{ -+ qDebug() << "drawImageMask"; -+#if 0 -+ unsigned char *buffer; -+ unsigned char *dest; -+ cairo_surface_t *image; -+ cairo_pattern_t *pattern; -+ int x, y; -+ ImageStream *imgStr; -+ Guchar *pix; -+ double *ctm; -+ cairo_matrix_t matrix; -+ int invert_bit; -+ int row_stride; -+ -+ row_stride = (width + 3) & ~3; -+ buffer = (unsigned char *) malloc (height * row_stride); -+ if (buffer == NULL) { -+ error(-1, "Unable to allocate memory for image."); -+ return; -+ } -+ -+ /* TODO: Do we want to cache these? */ -+ imgStr = new ImageStream(str, width, 1, 1); -+ imgStr->reset(); -+ -+ invert_bit = invert ? 1 : 0; -+ -+ for (y = 0; y < height; y++) { -+ pix = imgStr->getLine(); -+ dest = buffer + y * row_stride; -+ for (x = 0; x < width; x++) { -+ -+ if (pix[x] ^ invert_bit) -+ *dest++ = 0; -+ else -+ *dest++ = 255; -+ } -+ } -+ -+ image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_A8, -+ width, height, row_stride); -+ if (image == NULL) -+ return; -+ pattern = cairo_pattern_create_for_surface (image); -+ if (pattern == NULL) -+ return; -+ -+ ctm = state->getCTM(); -+ LOG (printf ("drawImageMask %dx%d, matrix: %f, %f, %f, %f, %f, %f\n", -+ width, height, ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5])); -+ matrix.xx = ctm[0] / width; -+ matrix.xy = -ctm[2] / height; -+ matrix.yx = ctm[1] / width; -+ matrix.yy = -ctm[3] / height; -+ matrix.x0 = ctm[2] + ctm[4]; -+ matrix.y0 = ctm[3] + ctm[5]; -+ cairo_matrix_invert (&matrix); -+ cairo_pattern_set_matrix (pattern, &matrix); -+ -+ cairo_pattern_set_filter (pattern, CAIRO_FILTER_BEST); -+ /* FIXME: Doesn't the image mask support any colorspace? */ -+ cairo_set_source_rgb (cairo, fill_color.r, fill_color.g, fill_color.b); -+ cairo_mask (cairo, pattern); -+ -+ cairo_pattern_destroy (pattern); -+ cairo_surface_destroy (image); -+ free (buffer); -+ imgStr->close (); -+ delete imgStr; -+#endif -+} -+ -+//TODO: lots more work here. -+void ArthurOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, -+ int width, int height, -+ GfxImageColorMap *colorMap, -+ bool interpolate, int *maskColors, bool inlineImg) -+{ -+ unsigned int *data; -+ unsigned int *line; -+ int x, y; -+ ImageStream *imgStr; -+ unsigned char *pix; -+ int i; -+ const double *ctm; -+ QMatrix matrix; -+ QImage image; -+ int stride; -+ -+ /* TODO: Do we want to cache these? */ -+ imgStr = new ImageStream(str, width, -+ colorMap->getNumPixelComps(), -+ colorMap->getBits()); -+ imgStr->reset(); -+ -+ image = QImage(width, height, QImage::Format_ARGB32); -+ data = (unsigned int *)image.bits(); -+ stride = image.bytesPerLine()/4; -+ for (y = 0; y < height; y++) { -+ pix = imgStr->getLine(); -+ line = data+y*stride; -+ colorMap->getRGBLine(pix, line, width); -+ -+ if (maskColors) { -+ for (x = 0; x < width; x++) { -+ for (i = 0; i < colorMap->getNumPixelComps(); ++i) { -+ if (pix[i] < maskColors[2*i] * 255|| -+ pix[i] > maskColors[2*i+1] * 255) { -+ *line = *line | 0xff000000; -+ break; -+ } -+ } -+ pix += colorMap->getNumPixelComps(); -+ line++; -+ } -+ } else { -+ for (x = 0; x < width; x++) { *line = *line | 0xff000000; line++; } -+ } -+ } -+ -+ ctm = state->getCTM(); -+ matrix.setMatrix(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, ctm[2] + ctm[4], ctm[3] + ctm[5]); -+ -+ m_painter->setMatrix(matrix, true); -+ m_painter->drawImage( QPoint(0,0), image ); -+ delete imgStr; -+ -+} -diff --git a/qt4/src/ArthurOutputDev.h b/qt4/src/ArthurOutputDev.h -new file mode 100644 -index 00000000..9d5e8679 ---- /dev/null -+++ b/qt4/src/ArthurOutputDev.h -@@ -0,0 +1,169 @@ -+//======================================================================== -+// -+// ArthurOutputDev.h -+// -+// Copyright 2003 Glyph & Cog, LLC -+// -+//======================================================================== -+ -+//======================================================================== -+// -+// Modified under the Poppler project - http://poppler.freedesktop.org -+// -+// All changes made under the Poppler project to this file are licensed -+// under GPL version 2 or later -+// -+// Copyright (C) 2005 Brad Hards -+// Copyright (C) 2005 Albert Astals Cid -+// Copyright (C) 2009, 2011 Carlos Garcia Campos -+// Copyright (C) 2010 Pino Toscano -+// Copyright (C) 2011 Andreas Hartmetz -+// Copyright (C) 2013 Thomas Freitag -+// -+// To see a description of the changes please see the Changelog file that -+// came with your tarball or type make ChangeLog if you are building from git -+// -+//======================================================================== -+ -+#ifndef ARTHUROUTPUTDEV_H -+#define ARTHUROUTPUTDEV_H -+ -+#ifdef USE_GCC_PRAGMAS -+#pragma interface -+#endif -+ -+#include "OutputDev.h" -+#include "GfxState.h" -+ -+#include -+ -+class GfxState; -+class GfxPath; -+class Gfx8BitFont; -+struct GfxRGB; -+ -+class SplashFont; -+class SplashFontEngine; -+struct SplashGlyphBitmap; -+ -+//------------------------------------------------------------------------ -+// ArthurOutputDev - Qt 4 QPainter renderer -+//------------------------------------------------------------------------ -+ -+class ArthurOutputDev: public OutputDev { -+public: -+ /** -+ * Describes how fonts are distorted (aka hinted) to fit the pixel grid. -+ * More hinting means sharper edges and less adherence to the true letter shapes. -+ */ -+ enum FontHinting { -+ NoHinting = 0, ///< Font shapes are left unchanged -+ SlightHinting, ///< Font shapes are distorted vertically only -+ FullHinting ///< Font shapes are distorted horizontally and vertically -+ }; -+ -+ // Constructor. -+ ArthurOutputDev(QPainter *painter ); -+ -+ // Destructor. -+ virtual ~ArthurOutputDev(); -+ -+ void setFontHinting(FontHinting hinting) { m_fontHinting = hinting; } -+ -+ //----- get info about output device -+ -+ // Does this device use upside-down coordinates? -+ // (Upside-down means (0,0) is the top left corner of the page.) -+ virtual bool upsideDown() { return true; } -+ -+ // Does this device use drawChar() or drawString()? -+ virtual bool useDrawChar() { return true; } -+ -+ // Does this device use beginType3Char/endType3Char? Otherwise, -+ // text in Type 3 fonts will be drawn with drawChar/drawString. -+ virtual bool interpretType3Chars() { return true; } -+ -+ //----- initialization and control -+ -+ // Start a page. -+ virtual void startPage(int pageNum, GfxState *state, XRef *xref); -+ -+ // End a page. -+ virtual void endPage(); -+ -+ //----- save/restore graphics state -+ virtual void saveState(GfxState *state); -+ virtual void restoreState(GfxState *state); -+ -+ //----- update graphics state -+ virtual void updateAll(GfxState *state); -+ virtual void updateCTM(GfxState *state, double m11, double m12, -+ double m21, double m22, double m31, double m32); -+ virtual void updateLineDash(GfxState *state); -+ virtual void updateFlatness(GfxState *state); -+ virtual void updateLineJoin(GfxState *state); -+ virtual void updateLineCap(GfxState *state); -+ virtual void updateMiterLimit(GfxState *state); -+ virtual void updateLineWidth(GfxState *state); -+ virtual void updateFillColor(GfxState *state); -+ virtual void updateStrokeColor(GfxState *state); -+ virtual void updateFillOpacity(GfxState *state); -+ virtual void updateStrokeOpacity(GfxState *state); -+ -+ //----- update text state -+ virtual void updateFont(GfxState *state); -+ -+ //----- path painting -+ virtual void stroke(GfxState *state); -+ virtual void fill(GfxState *state); -+ virtual void eoFill(GfxState *state); -+ -+ //----- path clipping -+ virtual void clip(GfxState *state); -+ virtual void eoClip(GfxState *state); -+ -+ //----- text drawing -+ // virtual void drawString(GfxState *state, GooString *s); -+ virtual void drawChar(GfxState *state, double x, double y, -+ double dx, double dy, -+ double originX, double originY, -+ CharCode code, int nBytes, Unicode *u, int uLen); -+ virtual bool beginType3Char(GfxState *state, double x, double y, -+ double dx, double dy, -+ CharCode code, Unicode *u, int uLen); -+ virtual void endType3Char(GfxState *state); -+ virtual void endTextObject(GfxState *state); -+ -+ //----- image drawing -+ virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, -+ int width, int height, bool invert, -+ bool interpolate, bool inlineImg); -+ virtual void drawImage(GfxState *state, Object *ref, Stream *str, -+ int width, int height, GfxImageColorMap *colorMap, -+ bool interpolate, int *maskColors, bool inlineImg); -+ -+ //----- Type 3 font operators -+ virtual void type3D0(GfxState *state, double wx, double wy); -+ virtual void type3D1(GfxState *state, double wx, double wy, -+ double llx, double lly, double urx, double ury); -+ -+ //----- special access -+ -+ // Called to indicate that a new PDF document has been loaded. -+ void startDoc(XRef *xrefA); -+ -+ bool isReverseVideo() { return false; } -+ -+private: -+ QPainter *m_painter; -+ FontHinting m_fontHinting; -+ QFont m_currentFont; -+ QPen m_currentPen; -+ QBrush m_currentBrush; -+ bool m_needFontUpdate; // set when the font needs to be updated -+ SplashFontEngine *m_fontEngine; -+ SplashFont *m_font; // current font -+ XRef *xref; // xref table for current document -+}; -+ -+#endif -diff --git a/qt4/src/CMakeLists.txt b/qt4/src/CMakeLists.txt -new file mode 100644 -index 00000000..f6547726 ---- /dev/null -+++ b/qt4/src/CMakeLists.txt -@@ -0,0 +1,54 @@ -+add_definitions(${QT4_DEFINITIONS}) -+ -+include_directories( -+ ${CMAKE_CURRENT_SOURCE_DIR} -+ ${QT4_INCLUDE_DIR} -+ ${CMAKE_CURRENT_BINARY_DIR} -+) -+ -+set(poppler_qt4_SRCS -+ poppler-annotation.cc -+ poppler-document.cc -+ poppler-embeddedfile.cc -+ poppler-fontinfo.cc -+ poppler-form.cc -+ poppler-link.cc -+ poppler-link-extractor.cc -+ poppler-movie.cc -+ poppler-optcontent.cc -+ poppler-page.cc -+ poppler-base-converter.cc -+ poppler-pdf-converter.cc -+ poppler-private.cc -+ poppler-ps-converter.cc -+ poppler-qiodeviceoutstream.cc -+ poppler-sound.cc -+ poppler-textbox.cc -+ poppler-page-transition.cc -+ poppler-media.cc -+ ArthurOutputDev.cc -+) -+qt4_automoc(${poppler_qt4_SRCS}) -+add_library(poppler-qt4 SHARED ${poppler_qt4_SRCS}) -+set_target_properties(poppler-qt4 PROPERTIES VERSION 4.11.0 SOVERSION 4) -+if(MINGW) -+ get_target_property(POPPLER_QT4_SOVERSION poppler-qt4 SOVERSION) -+ set_target_properties(poppler-qt4 PROPERTIES SUFFIX "-${POPPLER_QT4_SOVERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}") -+endif() -+target_link_libraries(poppler-qt4 poppler ${QT4_QTCORE_LIBRARY} ${QT4_QTGUI_LIBRARY} ${QT4_QTXML_LIBRARY}) -+if(MSVC) -+target_link_libraries(poppler-qt4 poppler ${poppler_LIBS}) -+endif() -+install(TARGETS poppler-qt4 RUNTIME DESTINATION bin LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) -+ -+install(FILES -+ poppler-qt4.h -+ poppler-link.h -+ poppler-annotation.h -+ poppler-form.h -+ poppler-optcontent.h -+ poppler-export.h -+ poppler-page-transition.h -+ poppler-media.h -+ DESTINATION include/poppler/qt4) -+ -diff --git a/qt4/src/Doxyfile b/qt4/src/Doxyfile -new file mode 100644 -index 00000000..e68690ac ---- /dev/null -+++ b/qt4/src/Doxyfile -@@ -0,0 +1,1637 @@ -+# Doxyfile 1.7.1 -+ -+# This file describes the settings to be used by the documentation system -+# doxygen (www.doxygen.org) for a project -+# -+# All text after a hash (#) is considered a comment and will be ignored -+# The format is: -+# TAG = value [value, ...] -+# For lists items can also be appended using: -+# TAG += value [value, ...] -+# Values that contain spaces should be placed between quotes (" ") -+ -+#--------------------------------------------------------------------------- -+# Project related configuration options -+#--------------------------------------------------------------------------- -+ -+# This tag specifies the encoding used for all characters in the config file -+# that follow. The default is UTF-8 which is also the encoding used for all -+# text before the first occurrence of this tag. Doxygen uses libiconv (or the -+# iconv built into libc) for the transcoding. See -+# http://www.gnu.org/software/libiconv for the list of possible encodings. -+ -+DOXYFILE_ENCODING = UTF-8 -+ -+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -+# by quotes) that should identify the project. -+ -+PROJECT_NAME = "Poppler Qt4 " -+ -+# The PROJECT_NUMBER tag can be used to enter a project or revision number. -+# This could be handy for archiving the generated documentation or -+# if some version control system is used. -+ -+PROJECT_NUMBER = 0.61.1 -+ -+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -+# base path where the generated documentation will be put. -+# If a relative path is entered, it will be relative to the location -+# where doxygen was started. If left blank the current directory will be used. -+ -+OUTPUT_DIRECTORY = -+ -+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -+# 4096 sub-directories (in 2 levels) under the output directory of each output -+# format and will distribute the generated files over these directories. -+# Enabling this option can be useful when feeding doxygen a huge amount of -+# source files, where putting all generated files in the same directory would -+# otherwise cause performance problems for the file system. -+ -+CREATE_SUBDIRS = NO -+ -+# The OUTPUT_LANGUAGE tag is used to specify the language in which all -+# documentation generated by doxygen is written. Doxygen will use this -+# information to generate all constant output in the proper language. -+# The default language is English, other supported languages are: -+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, -+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. -+ -+OUTPUT_LANGUAGE = English -+ -+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -+# include brief member descriptions after the members that are listed in -+# the file and class documentation (similar to JavaDoc). -+# Set to NO to disable this. -+ -+BRIEF_MEMBER_DESC = NO -+ -+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -+# the brief description of a member or function before the detailed description. -+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -+# brief descriptions will be completely suppressed. -+ -+REPEAT_BRIEF = YES -+ -+# This tag implements a quasi-intelligent brief description abbreviator -+# that is used to form the text in various listings. Each string -+# in this list, if found as the leading text of the brief description, will be -+# stripped from the text and the result after processing the whole list, is -+# used as the annotated text. Otherwise, the brief description is used as-is. -+# If left blank, the following values are used ("$name" is automatically -+# replaced with the name of the entity): "The $name class" "The $name widget" -+# "The $name file" "is" "provides" "specifies" "contains" -+# "represents" "a" "an" "the" -+ -+ABBREVIATE_BRIEF = -+ -+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -+# Doxygen will generate a detailed section even if there is only a brief -+# description. -+ -+ALWAYS_DETAILED_SEC = NO -+ -+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -+# inherited members of a class in the documentation of that class as if those -+# members were ordinary class members. Constructors, destructors and assignment -+# operators of the base classes will not be shown. -+ -+INLINE_INHERITED_MEMB = NO -+ -+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -+# path before files name in the file list and in the header files. If set -+# to NO the shortest path that makes the file name unique will be used. -+ -+FULL_PATH_NAMES = YES -+ -+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -+# can be used to strip a user-defined part of the path. Stripping is -+# only done if one of the specified strings matches the left-hand part of -+# the path. The tag can be used to show relative paths in the file list. -+# If left blank the directory from which doxygen is run is used as the -+# path to strip. -+ -+STRIP_FROM_PATH = -+ -+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -+# the path mentioned in the documentation of a class, which tells -+# the reader which header file to include in order to use a class. -+# If left blank only the name of the header file containing the class -+# definition is used. Otherwise one should specify the include paths that -+# are normally passed to the compiler using the -I flag. -+ -+STRIP_FROM_INC_PATH = -+ -+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -+# (but less readable) file names. This can be useful is your file systems -+# doesn't support long names like on DOS, Mac, or CD-ROM. -+ -+SHORT_NAMES = NO -+ -+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -+# will interpret the first line (until the first dot) of a JavaDoc-style -+# comment as the brief description. If set to NO, the JavaDoc -+# comments will behave just like regular Qt-style comments -+# (thus requiring an explicit @brief command for a brief description.) -+ -+JAVADOC_AUTOBRIEF = YES -+ -+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -+# interpret the first line (until the first dot) of a Qt-style -+# comment as the brief description. If set to NO, the comments -+# will behave just like regular Qt-style comments (thus requiring -+# an explicit \brief command for a brief description.) -+ -+QT_AUTOBRIEF = NO -+ -+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -+# treat a multi-line C++ special comment block (i.e. a block of //! or /// -+# comments) as a brief description. This used to be the default behaviour. -+# The new default is to treat a multi-line C++ comment block as a detailed -+# description. Set this tag to YES if you prefer the old behaviour instead. -+ -+MULTILINE_CPP_IS_BRIEF = NO -+ -+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -+# member inherits the documentation from any documented member that it -+# re-implements. -+ -+INHERIT_DOCS = YES -+ -+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -+# a new page for each member. If set to NO, the documentation of a member will -+# be part of the file/class/namespace that contains it. -+ -+SEPARATE_MEMBER_PAGES = NO -+ -+# The TAB_SIZE tag can be used to set the number of spaces in a tab. -+# Doxygen uses this value to replace tabs by spaces in code fragments. -+ -+TAB_SIZE = 8 -+ -+# This tag can be used to specify a number of aliases that acts -+# as commands in the documentation. An alias has the form "name=value". -+# For example adding "sideeffect=\par Side Effects:\n" will allow you to -+# put the command \sideeffect (or @sideeffect) in the documentation, which -+# will result in a user-defined paragraph with heading "Side Effects:". -+# You can put \n's in the value part of an alias to insert newlines. -+ -+ALIASES = -+ -+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -+# sources only. Doxygen will then generate output that is more tailored for C. -+# For instance, some of the names that are used will be different. The list -+# of all members will be omitted, etc. -+ -+OPTIMIZE_OUTPUT_FOR_C = NO -+ -+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -+# sources only. Doxygen will then generate output that is more tailored for -+# Java. For instance, namespaces will be presented as packages, qualified -+# scopes will look different, etc. -+ -+OPTIMIZE_OUTPUT_JAVA = NO -+ -+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -+# sources only. Doxygen will then generate output that is more tailored for -+# Fortran. -+ -+OPTIMIZE_FOR_FORTRAN = NO -+ -+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -+# sources. Doxygen will then generate output that is tailored for -+# VHDL. -+ -+OPTIMIZE_OUTPUT_VHDL = NO -+ -+# Doxygen selects the parser to use depending on the extension of the files it -+# parses. With this tag you can assign which parser to use for a given extension. -+# Doxygen has a built-in mapping, but you can override or extend it using this -+# tag. The format is ext=language, where ext is a file extension, and language -+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, -+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make -+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions -+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. -+ -+EXTENSION_MAPPING = -+ -+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -+# to include (a tag file for) the STL sources as input, then you should -+# set this tag to YES in order to let doxygen match functions declarations and -+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -+# func(std::string) {}). This also make the inheritance and collaboration -+# diagrams that involve STL classes more complete and accurate. -+ -+BUILTIN_STL_SUPPORT = NO -+ -+# If you use Microsoft's C++/CLI language, you should set this option to YES to -+# enable parsing support. -+ -+CPP_CLI_SUPPORT = NO -+ -+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -+# Doxygen will parse them like normal C++ but will assume all classes use public -+# instead of private inheritance when no explicit protection keyword is present. -+ -+SIP_SUPPORT = NO -+ -+# For Microsoft's IDL there are propget and propput attributes to indicate getter -+# and setter methods for a property. Setting this option to YES (the default) -+# will make doxygen to replace the get and set methods by a property in the -+# documentation. This will only work if the methods are indeed getting or -+# setting a simple type. If this is not the case, or you want to show the -+# methods anyway, you should set this option to NO. -+ -+IDL_PROPERTY_SUPPORT = YES -+ -+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -+# tag is set to YES, then doxygen will reuse the documentation of the first -+# member in the group (if any) for the other members of the group. By default -+# all members of a group must be documented explicitly. -+ -+DISTRIBUTE_GROUP_DOC = NO -+ -+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -+# the same type (for instance a group of public functions) to be put as a -+# subgroup of that type (e.g. under the Public Functions section). Set it to -+# NO to prevent subgrouping. Alternatively, this can be done per class using -+# the \nosubgrouping command. -+ -+SUBGROUPING = YES -+ -+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -+# is documented as struct, union, or enum with the name of the typedef. So -+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -+# with name TypeT. When disabled the typedef will appear as a member of a file, -+# namespace, or class. And the struct will be named TypeS. This can typically -+# be useful for C code in case the coding convention dictates that all compound -+# types are typedef'ed and only the typedef is referenced, never the tag name. -+ -+TYPEDEF_HIDES_STRUCT = NO -+ -+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -+# determine which symbols to keep in memory and which to flush to disk. -+# When the cache is full, less often used symbols will be written to disk. -+# For small to medium size projects (<1000 input files) the default value is -+# probably good enough. For larger projects a too small cache size can cause -+# doxygen to be busy swapping symbols to and from disk most of the time -+# causing a significant performance penality. -+# If the system has enough physical memory increasing the cache will improve the -+# performance by keeping more symbols in memory. Note that the value works on -+# a logarithmic scale so increasing the size by one will rougly double the -+# memory usage. The cache size is given by this formula: -+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -+# corresponding to a cache size of 2^16 = 65536 symbols -+ -+SYMBOL_CACHE_SIZE = 0 -+ -+#--------------------------------------------------------------------------- -+# Build related configuration options -+#--------------------------------------------------------------------------- -+ -+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -+# documentation are documented, even if no documentation was available. -+# Private class members and static file members will be hidden unless -+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES -+ -+EXTRACT_ALL = NO -+ -+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -+# will be included in the documentation. -+ -+EXTRACT_PRIVATE = NO -+ -+# If the EXTRACT_STATIC tag is set to YES all static members of a file -+# will be included in the documentation. -+ -+EXTRACT_STATIC = NO -+ -+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -+# defined locally in source files will be included in the documentation. -+# If set to NO only classes defined in header files are included. -+ -+EXTRACT_LOCAL_CLASSES = NO -+ -+# This flag is only useful for Objective-C code. When set to YES local -+# methods, which are defined in the implementation section but not in -+# the interface are included in the documentation. -+# If set to NO (the default) only methods in the interface are included. -+ -+EXTRACT_LOCAL_METHODS = NO -+ -+# If this flag is set to YES, the members of anonymous namespaces will be -+# extracted and appear in the documentation as a namespace called -+# 'anonymous_namespace{file}', where file will be replaced with the base -+# name of the file that contains the anonymous namespace. By default -+# anonymous namespace are hidden. -+ -+EXTRACT_ANON_NSPACES = NO -+ -+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -+# undocumented members of documented classes, files or namespaces. -+# If set to NO (the default) these members will be included in the -+# various overviews, but no documentation section is generated. -+# This option has no effect if EXTRACT_ALL is enabled. -+ -+HIDE_UNDOC_MEMBERS = NO -+ -+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -+# undocumented classes that are normally visible in the class hierarchy. -+# If set to NO (the default) these classes will be included in the various -+# overviews. This option has no effect if EXTRACT_ALL is enabled. -+ -+HIDE_UNDOC_CLASSES = NO -+ -+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -+# friend (class|struct|union) declarations. -+# If set to NO (the default) these declarations will be included in the -+# documentation. -+ -+HIDE_FRIEND_COMPOUNDS = YES -+ -+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -+# documentation blocks found inside the body of a function. -+# If set to NO (the default) these blocks will be appended to the -+# function's detailed documentation block. -+ -+HIDE_IN_BODY_DOCS = NO -+ -+# The INTERNAL_DOCS tag determines if documentation -+# that is typed after a \internal command is included. If the tag is set -+# to NO (the default) then the documentation will be excluded. -+# Set it to YES to include the internal documentation. -+ -+INTERNAL_DOCS = NO -+ -+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -+# file names in lower-case letters. If set to YES upper-case letters are also -+# allowed. This is useful if you have classes or files whose names only differ -+# in case and if your file system supports case sensitive file names. Windows -+# and Mac users are advised to set this option to NO. -+ -+CASE_SENSE_NAMES = YES -+ -+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -+# will show members with their full class and namespace scopes in the -+# documentation. If set to YES the scope will be hidden. -+ -+HIDE_SCOPE_NAMES = NO -+ -+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -+# will put a list of the files that are included by a file in the documentation -+# of that file. -+ -+SHOW_INCLUDE_FILES = YES -+ -+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -+# will list include files with double quotes in the documentation -+# rather than with sharp brackets. -+ -+FORCE_LOCAL_INCLUDES = NO -+ -+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -+# is inserted in the documentation for inline members. -+ -+INLINE_INFO = NO -+ -+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -+# will sort the (detailed) documentation of file and class members -+# alphabetically by member name. If set to NO the members will appear in -+# declaration order. -+ -+SORT_MEMBER_DOCS = YES -+ -+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -+# brief documentation of file, namespace and class members alphabetically -+# by member name. If set to NO (the default) the members will appear in -+# declaration order. -+ -+SORT_BRIEF_DOCS = YES -+ -+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -+# will sort the (brief and detailed) documentation of class members so that -+# constructors and destructors are listed first. If set to NO (the default) -+# the constructors will appear in the respective orders defined by -+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. -+ -+SORT_MEMBERS_CTORS_1ST = NO -+ -+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -+# hierarchy of group names into alphabetical order. If set to NO (the default) -+# the group names will appear in their defined order. -+ -+SORT_GROUP_NAMES = NO -+ -+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -+# sorted by fully-qualified names, including namespaces. If set to -+# NO (the default), the class list will be sorted only by class name, -+# not including the namespace part. -+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -+# Note: This option applies only to the class list, not to the -+# alphabetical list. -+ -+SORT_BY_SCOPE_NAME = YES -+ -+# The GENERATE_TODOLIST tag can be used to enable (YES) or -+# disable (NO) the todo list. This list is created by putting \todo -+# commands in the documentation. -+ -+GENERATE_TODOLIST = YES -+ -+# The GENERATE_TESTLIST tag can be used to enable (YES) or -+# disable (NO) the test list. This list is created by putting \test -+# commands in the documentation. -+ -+GENERATE_TESTLIST = YES -+ -+# The GENERATE_BUGLIST tag can be used to enable (YES) or -+# disable (NO) the bug list. This list is created by putting \bug -+# commands in the documentation. -+ -+GENERATE_BUGLIST = YES -+ -+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -+# disable (NO) the deprecated list. This list is created by putting -+# \deprecated commands in the documentation. -+ -+GENERATE_DEPRECATEDLIST= YES -+ -+# The ENABLED_SECTIONS tag can be used to enable conditional -+# documentation sections, marked by \if sectionname ... \endif. -+ -+ENABLED_SECTIONS = -+ -+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -+# the initial value of a variable or define consists of for it to appear in -+# the documentation. If the initializer consists of more lines than specified -+# here it will be hidden. Use a value of 0 to hide initializers completely. -+# The appearance of the initializer of individual variables and defines in the -+# documentation can be controlled using \showinitializer or \hideinitializer -+# command in the documentation regardless of this setting. -+ -+MAX_INITIALIZER_LINES = 30 -+ -+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -+# at the bottom of the documentation of classes and structs. If set to YES the -+# list will mention the files that were used to generate the documentation. -+ -+SHOW_USED_FILES = YES -+ -+# If the sources in your project are distributed over multiple directories -+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -+# in the documentation. The default is NO. -+ -+SHOW_DIRECTORIES = NO -+ -+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -+# This will remove the Files entry from the Quick Index and from the -+# Folder Tree View (if specified). The default is YES. -+ -+SHOW_FILES = YES -+ -+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -+# Namespaces page. -+# This will remove the Namespaces entry from the Quick Index -+# and from the Folder Tree View (if specified). The default is YES. -+ -+SHOW_NAMESPACES = YES -+ -+# The FILE_VERSION_FILTER tag can be used to specify a program or script that -+# doxygen should invoke to get the current version for each file (typically from -+# the version control system). Doxygen will invoke the program by executing (via -+# popen()) the command , where is the value of -+# the FILE_VERSION_FILTER tag, and is the name of an input file -+# provided by doxygen. Whatever the program writes to standard output -+# is used as the file version. See the manual for examples. -+ -+FILE_VERSION_FILTER = -+ -+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -+# by doxygen. The layout file controls the global structure of the generated -+# output files in an output format independent way. The create the layout file -+# that represents doxygen's defaults, run doxygen with the -l option. -+# You can optionally specify a file name after the option, if omitted -+# DoxygenLayout.xml will be used as the name of the layout file. -+ -+LAYOUT_FILE = -+ -+#--------------------------------------------------------------------------- -+# configuration options related to warning and progress messages -+#--------------------------------------------------------------------------- -+ -+# The QUIET tag can be used to turn on/off the messages that are generated -+# by doxygen. Possible values are YES and NO. If left blank NO is used. -+ -+QUIET = NO -+ -+# The WARNINGS tag can be used to turn on/off the warning messages that are -+# generated by doxygen. Possible values are YES and NO. If left blank -+# NO is used. -+ -+WARNINGS = YES -+ -+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -+# automatically be disabled. -+ -+WARN_IF_UNDOCUMENTED = YES -+ -+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -+# potential errors in the documentation, such as not documenting some -+# parameters in a documented function, or documenting parameters that -+# don't exist or using markup commands wrongly. -+ -+WARN_IF_DOC_ERROR = YES -+ -+# This WARN_NO_PARAMDOC option can be abled to get warnings for -+# functions that are documented, but have no documentation for their parameters -+# or return value. If set to NO (the default) doxygen will only warn about -+# wrong or incomplete parameter documentation, but not about the absence of -+# documentation. -+ -+WARN_NO_PARAMDOC = NO -+ -+# The WARN_FORMAT tag determines the format of the warning messages that -+# doxygen can produce. The string should contain the $file, $line, and $text -+# tags, which will be replaced by the file and line number from which the -+# warning originated and the warning text. Optionally the format may contain -+# $version, which will be replaced by the version of the file (if it could -+# be obtained via FILE_VERSION_FILTER) -+ -+WARN_FORMAT = "$file:$line: $text " -+ -+# The WARN_LOGFILE tag can be used to specify a file to which warning -+# and error messages should be written. If left blank the output is written -+# to stderr. -+ -+WARN_LOGFILE = -+ -+#--------------------------------------------------------------------------- -+# configuration options related to the input files -+#--------------------------------------------------------------------------- -+ -+# The INPUT tag can be used to specify the files and/or directories that contain -+# documented source files. You may enter file names like "myfile.cpp" or -+# directories like "/usr/src/myproject". Separate the files or directories -+# with spaces. -+ -+INPUT = Mainpage.dox \ -+ poppler-annotation.h \ -+ poppler-form.h \ -+ poppler-link.h \ -+ poppler-qt4.h \ -+ poppler-optcontent.h \ -+ poppler-page-transition.h -+ -+# This tag can be used to specify the character encoding of the source files -+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -+# also the default input encoding. Doxygen uses libiconv (or the iconv built -+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -+# the list of possible encodings. -+ -+INPUT_ENCODING = UTF-8 -+ -+# If the value of the INPUT tag contains directories, you can use the -+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -+# and *.h) to filter out the source-files in the directories. If left -+# blank the following patterns are tested: -+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 -+ -+FILE_PATTERNS = -+ -+# The RECURSIVE tag can be used to turn specify whether or not subdirectories -+# should be searched for input files as well. Possible values are YES and NO. -+# If left blank NO is used. -+ -+RECURSIVE = NO -+ -+# The EXCLUDE tag can be used to specify files and/or directories that should -+# excluded from the INPUT source files. This way you can easily exclude a -+# subdirectory from a directory tree whose root is specified with the INPUT tag. -+ -+EXCLUDE = -+ -+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -+# directories that are symbolic links (a Unix filesystem feature) are excluded -+# from the input. -+ -+EXCLUDE_SYMLINKS = NO -+ -+# If the value of the INPUT tag contains directories, you can use the -+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -+# certain files from those directories. Note that the wildcards are matched -+# against the file with absolute path, so to exclude all test directories -+# for example use the pattern */test/* -+ -+EXCLUDE_PATTERNS = -+ -+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -+# (namespaces, classes, functions, etc.) that should be excluded from the -+# output. The symbol name can be a fully qualified name, a word, or if the -+# wildcard * is used, a substring. Examples: ANamespace, AClass, -+# AClass::ANamespace, ANamespace::*Test -+ -+EXCLUDE_SYMBOLS = -+ -+# The EXAMPLE_PATH tag can be used to specify one or more files or -+# directories that contain example code fragments that are included (see -+# the \include command). -+ -+EXAMPLE_PATH = -+ -+# If the value of the EXAMPLE_PATH tag contains directories, you can use the -+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -+# and *.h) to filter out the source-files in the directories. If left -+# blank all files are included. -+ -+EXAMPLE_PATTERNS = -+ -+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -+# searched for input files to be used with the \include or \dontinclude -+# commands irrespective of the value of the RECURSIVE tag. -+# Possible values are YES and NO. If left blank NO is used. -+ -+EXAMPLE_RECURSIVE = NO -+ -+# The IMAGE_PATH tag can be used to specify one or more files or -+# directories that contain image that are included in the documentation (see -+# the \image command). -+ -+IMAGE_PATH = -+ -+# The INPUT_FILTER tag can be used to specify a program that doxygen should -+# invoke to filter for each input file. Doxygen will invoke the filter program -+# by executing (via popen()) the command , where -+# is the value of the INPUT_FILTER tag, and is the name of an -+# input file. Doxygen will then use the output that the filter program writes -+# to standard output. -+# If FILTER_PATTERNS is specified, this tag will be -+# ignored. -+ -+INPUT_FILTER = -+ -+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -+# basis. -+# Doxygen will compare the file name with each pattern and apply the -+# filter if there is a match. -+# The filters are a list of the form: -+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -+# is applied to all files. -+ -+FILTER_PATTERNS = -+ -+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -+# INPUT_FILTER) will be used to filter the input files when producing source -+# files to browse (i.e. when SOURCE_BROWSER is set to YES). -+ -+FILTER_SOURCE_FILES = NO -+ -+#--------------------------------------------------------------------------- -+# configuration options related to source browsing -+#--------------------------------------------------------------------------- -+ -+# If the SOURCE_BROWSER tag is set to YES then a list of source files will -+# be generated. Documented entities will be cross-referenced with these sources. -+# Note: To get rid of all source code in the generated output, make sure also -+# VERBATIM_HEADERS is set to NO. -+ -+SOURCE_BROWSER = NO -+ -+# Setting the INLINE_SOURCES tag to YES will include the body -+# of functions and classes directly in the documentation. -+ -+INLINE_SOURCES = NO -+ -+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -+# doxygen to hide any special comment blocks from generated source code -+# fragments. Normal C and C++ comments will always remain visible. -+ -+STRIP_CODE_COMMENTS = YES -+ -+# If the REFERENCED_BY_RELATION tag is set to YES -+# then for each documented function all documented -+# functions referencing it will be listed. -+ -+REFERENCED_BY_RELATION = YES -+ -+# If the REFERENCES_RELATION tag is set to YES -+# then for each documented function all documented entities -+# called/used by that function will be listed. -+ -+REFERENCES_RELATION = YES -+ -+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -+# link to the source code. -+# Otherwise they will link to the documentation. -+ -+REFERENCES_LINK_SOURCE = YES -+ -+# If the USE_HTAGS tag is set to YES then the references to source code -+# will point to the HTML generated by the htags(1) tool instead of doxygen -+# built-in source browser. The htags tool is part of GNU's global source -+# tagging system (see http://www.gnu.org/software/global/global.html). You -+# will need version 4.8.6 or higher. -+ -+USE_HTAGS = NO -+ -+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -+# will generate a verbatim copy of the header file for each class for -+# which an include is specified. Set to NO to disable this. -+ -+VERBATIM_HEADERS = YES -+ -+#--------------------------------------------------------------------------- -+# configuration options related to the alphabetical class index -+#--------------------------------------------------------------------------- -+ -+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -+# of all compounds will be generated. Enable this if the project -+# contains a lot of classes, structs, unions or interfaces. -+ -+ALPHABETICAL_INDEX = YES -+ -+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -+# in which this list will be split (can be a number in the range [1..20]) -+ -+COLS_IN_ALPHA_INDEX = 5 -+ -+# In case all classes in a project start with a common prefix, all -+# classes will be put under the same header in the alphabetical index. -+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -+# should be ignored while generating the index headers. -+ -+IGNORE_PREFIX = -+ -+#--------------------------------------------------------------------------- -+# configuration options related to the HTML output -+#--------------------------------------------------------------------------- -+ -+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -+# generate HTML output. -+ -+GENERATE_HTML = YES -+ -+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -+# If a relative path is entered the value of OUTPUT_DIRECTORY will be -+# put in front of it. If left blank `html' will be used as the default path. -+ -+HTML_OUTPUT = APIDOCS-html -+ -+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -+# doxygen will generate files with .html extension. -+ -+HTML_FILE_EXTENSION = .html -+ -+# The HTML_HEADER tag can be used to specify a personal HTML header for -+# each generated HTML page. If it is left blank doxygen will generate a -+# standard header. -+ -+HTML_HEADER = -+ -+# The HTML_FOOTER tag can be used to specify a personal HTML footer for -+# each generated HTML page. If it is left blank doxygen will generate a -+# standard footer. -+ -+HTML_FOOTER = -+ -+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -+# style sheet that is used by each HTML page. It can be used to -+# fine-tune the look of the HTML output. If the tag is left blank doxygen -+# will generate a default style sheet. Note that doxygen will try to copy -+# the style sheet file to the HTML output directory, so don't put your own -+# stylesheet in the HTML output directory as well, or it will be erased! -+ -+HTML_STYLESHEET = -+ -+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -+# Doxygen will adjust the colors in the stylesheet and background images -+# according to this color. Hue is specified as an angle on a colorwheel, -+# see http://en.wikipedia.org/wiki/Hue for more information. -+# For instance the value 0 represents red, 60 is yellow, 120 is green, -+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -+# The allowed range is 0 to 359. -+ -+HTML_COLORSTYLE_HUE = 220 -+ -+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -+# the colors in the HTML output. For a value of 0 the output will use -+# grayscales only. A value of 255 will produce the most vivid colors. -+ -+HTML_COLORSTYLE_SAT = 100 -+ -+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -+# the luminance component of the colors in the HTML output. Values below -+# 100 gradually make the output lighter, whereas values above 100 make -+# the output darker. The value divided by 100 is the actual gamma applied, -+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -+# and 100 does not change the gamma. -+ -+HTML_COLORSTYLE_GAMMA = 80 -+ -+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -+# page will contain the date and time when the page was generated. Setting -+# this to NO can help when comparing the output of multiple runs. -+ -+HTML_TIMESTAMP = YES -+ -+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -+# files or namespaces will be aligned in HTML using tables. If set to -+# NO a bullet list will be used. -+ -+HTML_ALIGN_MEMBERS = YES -+ -+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -+# documentation will contain sections that can be hidden and shown after the -+# page has loaded. For this to work a browser that supports -+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). -+ -+HTML_DYNAMIC_SECTIONS = NO -+ -+# If the GENERATE_DOCSET tag is set to YES, additional index files -+# will be generated that can be used as input for Apple's Xcode 3 -+# integrated development environment, introduced with OSX 10.5 (Leopard). -+# To create a documentation set, doxygen will generate a Makefile in the -+# HTML output directory. Running make will produce the docset in that -+# directory and running "make install" will install the docset in -+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -+# it at startup. -+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -+# for more information. -+ -+GENERATE_DOCSET = NO -+ -+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -+# feed. A documentation feed provides an umbrella under which multiple -+# documentation sets from a single provider (such as a company or product suite) -+# can be grouped. -+ -+DOCSET_FEEDNAME = "Doxygen generated docs" -+ -+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -+# should uniquely identify the documentation set bundle. This should be a -+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -+# will append .docset to the name. -+ -+DOCSET_BUNDLE_ID = org.doxygen.Project -+ -+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify -+# the documentation publisher. This should be a reverse domain-name style -+# string, e.g. com.mycompany.MyDocSet.documentation. -+ -+DOCSET_PUBLISHER_ID = org.doxygen.Publisher -+ -+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. -+ -+DOCSET_PUBLISHER_NAME = Publisher -+ -+# If the GENERATE_HTMLHELP tag is set to YES, additional index files -+# will be generated that can be used as input for tools like the -+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -+# of the generated HTML documentation. -+ -+GENERATE_HTMLHELP = NO -+ -+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -+# be used to specify the file name of the resulting .chm file. You -+# can add a path in front of the file if the result should not be -+# written to the html output directory. -+ -+CHM_FILE = -+ -+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -+# be used to specify the location (absolute path including file name) of -+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -+# the HTML help compiler on the generated index.hhp. -+ -+HHC_LOCATION = -+ -+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -+# controls if a separate .chi index file is generated (YES) or that -+# it should be included in the master .chm file (NO). -+ -+GENERATE_CHI = NO -+ -+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -+# is used to encode HtmlHelp index (hhk), content (hhc) and project file -+# content. -+ -+CHM_INDEX_ENCODING = -+ -+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -+# controls whether a binary table of contents is generated (YES) or a -+# normal table of contents (NO) in the .chm file. -+ -+BINARY_TOC = NO -+ -+# The TOC_EXPAND flag can be set to YES to add extra items for group members -+# to the contents of the HTML help documentation and to the tree view. -+ -+TOC_EXPAND = NO -+ -+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -+# that can be used as input for Qt's qhelpgenerator to generate a -+# Qt Compressed Help (.qch) of the generated HTML documentation. -+ -+GENERATE_QHP = YES -+ -+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -+# be used to specify the file name of the resulting .qch file. -+# The path specified is relative to the HTML output folder. -+ -+QCH_FILE = poppler-qt4.qch -+ -+# The QHP_NAMESPACE tag specifies the namespace to use when generating -+# Qt Help Project output. For more information please see -+# http://doc.trolltech.com/qthelpproject.html#namespace -+ -+QHP_NAMESPACE = org.freedesktop.poppler.qt4 -+ -+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -+# Qt Help Project output. For more information please see -+# http://doc.trolltech.com/qthelpproject.html#virtual-folders -+ -+QHP_VIRTUAL_FOLDER = doc -+ -+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -+# add. For more information please see -+# http://doc.trolltech.com/qthelpproject.html#custom-filters -+ -+QHP_CUST_FILTER_NAME = "Poppler 0.15.0" -+ -+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -+# custom filter to add. For more information please see -+# -+# Qt Help Project / Custom Filters. -+ -+QHP_CUST_FILTER_ATTRS = poppler -+ -+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -+# project's -+# filter section matches. -+# -+# Qt Help Project / Filter Attributes. -+ -+QHP_SECT_FILTER_ATTRS = poppler -+ -+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -+# be used to specify the location of Qt's qhelpgenerator. -+# If non-empty doxygen will try to run qhelpgenerator on the generated -+# .qhp file. -+ -+QHG_LOCATION = qhelpgenerator -+ -+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -+# will be generated, which together with the HTML files, form an Eclipse help -+# plugin. To install this plugin and make it available under the help contents -+# menu in Eclipse, the contents of the directory containing the HTML and XML -+# files needs to be copied into the plugins directory of eclipse. The name of -+# the directory within the plugins directory should be the same as -+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -+# the help appears. -+ -+GENERATE_ECLIPSEHELP = NO -+ -+# A unique identifier for the eclipse help plugin. When installing the plugin -+# the directory name containing the HTML and XML files should also have -+# this name. -+ -+ECLIPSE_DOC_ID = org.doxygen.Project -+ -+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -+# top of each HTML page. The value NO (the default) enables the index and -+# the value YES disables it. -+ -+DISABLE_INDEX = NO -+ -+# This tag can be used to set the number of enum values (range [1..20]) -+# that doxygen will group on one line in the generated HTML documentation. -+ -+ENUM_VALUES_PER_LINE = 4 -+ -+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -+# structure should be generated to display hierarchical information. -+# If the tag value is set to YES, a side panel will be generated -+# containing a tree-like index structure (just like the one that -+# is generated for HTML Help). For this to work a browser that supports -+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -+# Windows users are probably better off using the HTML help feature. -+ -+GENERATE_TREEVIEW = NO -+ -+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -+# and Class Hierarchy pages using a tree view instead of an ordered list. -+ -+USE_INLINE_TREES = NO -+ -+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -+# used to set the initial width (in pixels) of the frame in which the tree -+# is shown. -+ -+TREEVIEW_WIDTH = 250 -+ -+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -+# links to external symbols imported via tag files in a separate window. -+ -+EXT_LINKS_IN_WINDOW = NO -+ -+# Use this tag to change the font size of Latex formulas included -+# as images in the HTML documentation. The default is 10. Note that -+# when you change the font size after a successful doxygen run you need -+# to manually remove any form_*.png images from the HTML output directory -+# to force them to be regenerated. -+ -+FORMULA_FONTSIZE = 10 -+ -+# Use the FORMULA_TRANPARENT tag to determine whether or not the images -+# generated for formulas are transparent PNGs. Transparent PNGs are -+# not supported properly for IE 6.0, but are supported on all modern browsers. -+# Note that when changing this option you need to delete any form_*.png files -+# in the HTML output before the changes have effect. -+ -+FORMULA_TRANSPARENT = YES -+ -+# When the SEARCHENGINE tag is enabled doxygen will generate a search box -+# for the HTML output. The underlying search engine uses javascript -+# and DHTML and should work on any modern browser. Note that when using -+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -+# (GENERATE_DOCSET) there is already a search function so this one should -+# typically be disabled. For large projects the javascript based search engine -+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. -+ -+SEARCHENGINE = NO -+ -+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be -+# implemented using a PHP enabled web server instead of at the web client -+# using Javascript. Doxygen will generate the search PHP script and index -+# file to put on the web server. The advantage of the server -+# based approach is that it scales better to large projects and allows -+# full text search. The disadvances is that it is more difficult to setup -+# and does not have live searching capabilities. -+ -+SERVER_BASED_SEARCH = NO -+ -+#--------------------------------------------------------------------------- -+# configuration options related to the LaTeX output -+#--------------------------------------------------------------------------- -+ -+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -+# generate Latex output. -+ -+GENERATE_LATEX = YES -+ -+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -+# If a relative path is entered the value of OUTPUT_DIRECTORY will be -+# put in front of it. If left blank `latex' will be used as the default path. -+ -+LATEX_OUTPUT = APIDOCS-latex -+ -+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -+# invoked. If left blank `latex' will be used as the default command name. -+# Note that when enabling USE_PDFLATEX this option is only used for -+# generating bitmaps for formulas in the HTML output, but not in the -+# Makefile that is written to the output directory. -+ -+LATEX_CMD_NAME = latex -+ -+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -+# generate index for LaTeX. If left blank `makeindex' will be used as the -+# default command name. -+ -+MAKEINDEX_CMD_NAME = makeindex -+ -+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -+# LaTeX documents. This may be useful for small projects and may help to -+# save some trees in general. -+ -+COMPACT_LATEX = NO -+ -+# The PAPER_TYPE tag can be used to set the paper type that is used -+# by the printer. Possible values are: a4, a4wide, letter, legal and -+# executive. If left blank a4wide will be used. -+ -+PAPER_TYPE = a4wide -+ -+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -+# packages that should be included in the LaTeX output. -+ -+EXTRA_PACKAGES = -+ -+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -+# the generated latex document. The header should contain everything until -+# the first chapter. If it is left blank doxygen will generate a -+# standard header. Notice: only use this tag if you know what you are doing! -+ -+LATEX_HEADER = -+ -+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -+# is prepared for conversion to pdf (using ps2pdf). The pdf file will -+# contain links (just like the HTML output) instead of page references -+# This makes the output suitable for online browsing using a pdf viewer. -+ -+PDF_HYPERLINKS = NO -+ -+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -+# plain latex in the generated Makefile. Set this option to YES to get a -+# higher quality PDF documentation. -+ -+USE_PDFLATEX = NO -+ -+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -+# command to the generated LaTeX files. This will instruct LaTeX to keep -+# running if errors occur, instead of asking the user for help. -+# This option is also used when generating formulas in HTML. -+ -+LATEX_BATCHMODE = NO -+ -+# If LATEX_HIDE_INDICES is set to YES then doxygen will not -+# include the index chapters (such as File Index, Compound Index, etc.) -+# in the output. -+ -+LATEX_HIDE_INDICES = NO -+ -+# If LATEX_SOURCE_CODE is set to YES then doxygen will include -+# source code with syntax highlighting in the LaTeX output. -+# Note that which sources are shown also depends on other settings -+# such as SOURCE_BROWSER. -+ -+LATEX_SOURCE_CODE = NO -+ -+#--------------------------------------------------------------------------- -+# configuration options related to the RTF output -+#--------------------------------------------------------------------------- -+ -+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -+# The RTF output is optimized for Word 97 and may not look very pretty with -+# other RTF readers or editors. -+ -+GENERATE_RTF = NO -+ -+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -+# If a relative path is entered the value of OUTPUT_DIRECTORY will be -+# put in front of it. If left blank `rtf' will be used as the default path. -+ -+RTF_OUTPUT = rtf -+ -+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -+# RTF documents. This may be useful for small projects and may help to -+# save some trees in general. -+ -+COMPACT_RTF = NO -+ -+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -+# will contain hyperlink fields. The RTF file will -+# contain links (just like the HTML output) instead of page references. -+# This makes the output suitable for online browsing using WORD or other -+# programs which support those fields. -+# Note: wordpad (write) and others do not support links. -+ -+RTF_HYPERLINKS = NO -+ -+# Load stylesheet definitions from file. Syntax is similar to doxygen's -+# config file, i.e. a series of assignments. You only have to provide -+# replacements, missing definitions are set to their default value. -+ -+RTF_STYLESHEET_FILE = -+ -+# Set optional variables used in the generation of an rtf document. -+# Syntax is similar to doxygen's config file. -+ -+RTF_EXTENSIONS_FILE = -+ -+#--------------------------------------------------------------------------- -+# configuration options related to the man page output -+#--------------------------------------------------------------------------- -+ -+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -+# generate man pages -+ -+GENERATE_MAN = NO -+ -+# The MAN_OUTPUT tag is used to specify where the man pages will be put. -+# If a relative path is entered the value of OUTPUT_DIRECTORY will be -+# put in front of it. If left blank `man' will be used as the default path. -+ -+MAN_OUTPUT = man -+ -+# The MAN_EXTENSION tag determines the extension that is added to -+# the generated man pages (default is the subroutine's section .3) -+ -+MAN_EXTENSION = .3 -+ -+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -+# then it will generate one additional man file for each entity -+# documented in the real man page(s). These additional files -+# only source the real man page, but without them the man command -+# would be unable to find the correct page. The default is NO. -+ -+MAN_LINKS = NO -+ -+#--------------------------------------------------------------------------- -+# configuration options related to the XML output -+#--------------------------------------------------------------------------- -+ -+# If the GENERATE_XML tag is set to YES Doxygen will -+# generate an XML file that captures the structure of -+# the code including all documentation. -+ -+GENERATE_XML = NO -+ -+# The XML_OUTPUT tag is used to specify where the XML pages will be put. -+# If a relative path is entered the value of OUTPUT_DIRECTORY will be -+# put in front of it. If left blank `xml' will be used as the default path. -+ -+XML_OUTPUT = xml -+ -+# The XML_SCHEMA tag can be used to specify an XML schema, -+# which can be used by a validating XML parser to check the -+# syntax of the XML files. -+ -+XML_SCHEMA = -+ -+# The XML_DTD tag can be used to specify an XML DTD, -+# which can be used by a validating XML parser to check the -+# syntax of the XML files. -+ -+XML_DTD = -+ -+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -+# dump the program listings (including syntax highlighting -+# and cross-referencing information) to the XML output. Note that -+# enabling this will significantly increase the size of the XML output. -+ -+XML_PROGRAMLISTING = YES -+ -+#--------------------------------------------------------------------------- -+# configuration options for the AutoGen Definitions output -+#--------------------------------------------------------------------------- -+ -+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -+# generate an AutoGen Definitions (see autogen.sf.net) file -+# that captures the structure of the code including all -+# documentation. Note that this feature is still experimental -+# and incomplete at the moment. -+ -+GENERATE_AUTOGEN_DEF = NO -+ -+#--------------------------------------------------------------------------- -+# configuration options related to the Perl module output -+#--------------------------------------------------------------------------- -+ -+# If the GENERATE_PERLMOD tag is set to YES Doxygen will -+# generate a Perl module file that captures the structure of -+# the code including all documentation. Note that this -+# feature is still experimental and incomplete at the -+# moment. -+ -+GENERATE_PERLMOD = NO -+ -+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -+# the necessary Makefile rules, Perl scripts and LaTeX code to be able -+# to generate PDF and DVI output from the Perl module output. -+ -+PERLMOD_LATEX = NO -+ -+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -+# nicely formatted so it can be parsed by a human reader. -+# This is useful -+# if you want to understand what is going on. -+# On the other hand, if this -+# tag is set to NO the size of the Perl module output will be much smaller -+# and Perl will parse it just the same. -+ -+PERLMOD_PRETTY = YES -+ -+# The names of the make variables in the generated doxyrules.make file -+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -+# This is useful so different doxyrules.make files included by the same -+# Makefile don't overwrite each other's variables. -+ -+PERLMOD_MAKEVAR_PREFIX = -+ -+#--------------------------------------------------------------------------- -+# Configuration options related to the preprocessor -+#--------------------------------------------------------------------------- -+ -+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -+# evaluate all C-preprocessor directives found in the sources and include -+# files. -+ -+ENABLE_PREPROCESSING = YES -+ -+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -+# names in the source code. If set to NO (the default) only conditional -+# compilation will be performed. Macro expansion can be done in a controlled -+# way by setting EXPAND_ONLY_PREDEF to YES. -+ -+MACRO_EXPANSION = YES -+ -+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -+# then the macro expansion is limited to the macros specified with the -+# PREDEFINED and EXPAND_AS_DEFINED tags. -+ -+EXPAND_ONLY_PREDEF = YES -+ -+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -+# in the INCLUDE_PATH (see below) will be search if a #include is found. -+ -+SEARCH_INCLUDES = YES -+ -+# The INCLUDE_PATH tag can be used to specify one or more directories that -+# contain include files that are not input files but should be processed by -+# the preprocessor. -+ -+INCLUDE_PATH = -+ -+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -+# patterns (like *.h and *.hpp) to filter out the header-files in the -+# directories. If left blank, the patterns specified with FILE_PATTERNS will -+# be used. -+ -+INCLUDE_FILE_PATTERNS = -+ -+# The PREDEFINED tag can be used to specify one or more macro names that -+# are defined before the preprocessor is started (similar to the -D option of -+# gcc). The argument of the tag is a list of macros of the form: name -+# or name=definition (no spaces). If the definition and the = are -+# omitted =1 is assumed. To prevent a macro definition from being -+# undefined via #undef or recursively expanded use the := operator -+# instead of the = operator. -+ -+PREDEFINED = "Q_DECL_DEPRECATED=" \ -+ "POPPLER_QT4_EXPORT=" -+ -+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -+# this tag can be used to specify a list of macro names that should be expanded. -+# The macro definition that is found in the sources will be used. -+# Use the PREDEFINED tag if you want to use a different macro definition. -+ -+EXPAND_AS_DEFINED = -+ -+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -+# doxygen's preprocessor will remove all function-like macros that are alone -+# on a line, have an all uppercase name, and do not end with a semicolon. Such -+# function macros are typically used for boiler-plate code, and will confuse -+# the parser if not removed. -+ -+SKIP_FUNCTION_MACROS = YES -+ -+#--------------------------------------------------------------------------- -+# Configuration::additions related to external references -+#--------------------------------------------------------------------------- -+ -+# The TAGFILES option can be used to specify one or more tagfiles. -+# Optionally an initial location of the external documentation -+# can be added for each tagfile. The format of a tag file without -+# this location is as follows: -+# -+# TAGFILES = file1 file2 ... -+# Adding location for the tag files is done as follows: -+# -+# TAGFILES = file1=loc1 "file2 = loc2" ... -+# where "loc1" and "loc2" can be relative or absolute paths or -+# URLs. If a location is present for each tag, the installdox tool -+# does not have to be run to correct the links. -+# Note that each tag file must have a unique name -+# (where the name does NOT include the path) -+# If a tag file is not located in the directory in which doxygen -+# is run, you must also specify the path to the tagfile here. -+ -+TAGFILES = -+ -+# When a file name is specified after GENERATE_TAGFILE, doxygen will create -+# a tag file that is based on the input files it reads. -+ -+GENERATE_TAGFILE = -+ -+# If the ALLEXTERNALS tag is set to YES all external classes will be listed -+# in the class index. If set to NO only the inherited external classes -+# will be listed. -+ -+ALLEXTERNALS = NO -+ -+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -+# in the modules index. If set to NO, only the current project's groups will -+# be listed. -+ -+EXTERNAL_GROUPS = YES -+ -+# The PERL_PATH should be the absolute path and name of the perl script -+# interpreter (i.e. the result of `which perl'). -+ -+PERL_PATH = /usr/bin/perl -+ -+#--------------------------------------------------------------------------- -+# Configuration options related to the dot tool -+#--------------------------------------------------------------------------- -+ -+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -+# or super classes. Setting the tag to NO turns the diagrams off. Note that -+# this option is superseded by the HAVE_DOT option below. This is only a -+# fallback. It is recommended to install and use dot, since it yields more -+# powerful graphs. -+ -+CLASS_DIAGRAMS = YES -+ -+# You can define message sequence charts within doxygen comments using the \msc -+# command. Doxygen will then run the mscgen tool (see -+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -+# documentation. The MSCGEN_PATH tag allows you to specify the directory where -+# the mscgen tool resides. If left empty the tool is assumed to be found in the -+# default search path. -+ -+MSCGEN_PATH = -+ -+# If set to YES, the inheritance and collaboration graphs will hide -+# inheritance and usage relations if the target is undocumented -+# or is not a class. -+ -+HIDE_UNDOC_RELATIONS = YES -+ -+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -+# available from the path. This tool is part of Graphviz, a graph visualization -+# toolkit from AT&T and Lucent Bell Labs. The other options in this section -+# have no effect if this option is set to NO (the default) -+ -+HAVE_DOT = YES -+ -+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is -+# allowed to run in parallel. When set to 0 (the default) doxygen will -+# base this on the number of processors available in the system. You can set it -+# explicitly to a value larger than 0 to get control over the balance -+# between CPU load and processing speed. -+ -+DOT_NUM_THREADS = 0 -+ -+# By default doxygen will write a font called FreeSans.ttf to the output -+# directory and reference it in all dot files that doxygen generates. This -+# font does not include all possible unicode characters however, so when you need -+# these (or just want a differently looking font) you can specify the font name -+# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -+# which can be done by putting it in a standard location or by setting the -+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -+# containing the font. -+ -+DOT_FONTNAME = FreeSans.ttf -+ -+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -+# The default size is 10pt. -+ -+DOT_FONTSIZE = 10 -+ -+# By default doxygen will tell dot to use the output directory to look for the -+# FreeSans.ttf font (which doxygen will put there itself). If you specify a -+# different font using DOT_FONTNAME you can set the path where dot -+# can find it using this tag. -+ -+DOT_FONTPATH = -+ -+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -+# will generate a graph for each documented class showing the direct and -+# indirect inheritance relations. Setting this tag to YES will force the -+# the CLASS_DIAGRAMS tag to NO. -+ -+CLASS_GRAPH = YES -+ -+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -+# will generate a graph for each documented class showing the direct and -+# indirect implementation dependencies (inheritance, containment, and -+# class references variables) of the class with other documented classes. -+ -+COLLABORATION_GRAPH = YES -+ -+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -+# will generate a graph for groups, showing the direct groups dependencies -+ -+GROUP_GRAPHS = YES -+ -+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -+# collaboration diagrams in a style similar to the OMG's Unified Modeling -+# Language. -+ -+UML_LOOK = NO -+ -+# If set to YES, the inheritance and collaboration graphs will show the -+# relations between templates and their instances. -+ -+TEMPLATE_RELATIONS = NO -+ -+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -+# tags are set to YES then doxygen will generate a graph for each documented -+# file showing the direct and indirect include dependencies of the file with -+# other documented files. -+ -+INCLUDE_GRAPH = YES -+ -+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -+# documented header file showing the documented files that directly or -+# indirectly include this file. -+ -+INCLUDED_BY_GRAPH = YES -+ -+# If the CALL_GRAPH and HAVE_DOT options are set to YES then -+# doxygen will generate a call dependency graph for every global function -+# or class method. Note that enabling this option will significantly increase -+# the time of a run. So in most cases it will be better to enable call graphs -+# for selected functions only using the \callgraph command. -+ -+CALL_GRAPH = NO -+ -+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -+# doxygen will generate a caller dependency graph for every global function -+# or class method. Note that enabling this option will significantly increase -+# the time of a run. So in most cases it will be better to enable caller -+# graphs for selected functions only using the \callergraph command. -+ -+CALLER_GRAPH = NO -+ -+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -+# will graphical hierarchy of all classes instead of a textual one. -+ -+GRAPHICAL_HIERARCHY = YES -+ -+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -+# then doxygen will show the dependencies a directory has on other directories -+# in a graphical way. The dependency relations are determined by the #include -+# relations between the files in the directories. -+ -+DIRECTORY_GRAPH = YES -+ -+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -+# generated by dot. Possible values are png, jpg, or gif -+# If left blank png will be used. -+ -+DOT_IMAGE_FORMAT = png -+ -+# The tag DOT_PATH can be used to specify the path where the dot tool can be -+# found. If left blank, it is assumed the dot tool can be found in the path. -+ -+DOT_PATH = -+ -+# The DOTFILE_DIRS tag can be used to specify one or more directories that -+# contain dot files that are included in the documentation (see the -+# \dotfile command). -+ -+DOTFILE_DIRS = -+ -+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -+# nodes that will be shown in the graph. If the number of nodes in a graph -+# becomes larger than this value, doxygen will truncate the graph, which is -+# visualized by representing a node as a red box. Note that doxygen if the -+# number of direct children of the root node in a graph is already larger than -+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. -+ -+DOT_GRAPH_MAX_NODES = 50 -+ -+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -+# graphs generated by dot. A depth value of 3 means that only nodes reachable -+# from the root by following a path via at most 3 edges will be shown. Nodes -+# that lay further from the root node will be omitted. Note that setting this -+# option to 1 or 2 may greatly reduce the computation time needed for large -+# code bases. Also note that the size of a graph can be further restricted by -+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. -+ -+MAX_DOT_GRAPH_DEPTH = 0 -+ -+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -+# background. This is disabled by default, because dot on Windows does not -+# seem to support this out of the box. Warning: Depending on the platform used, -+# enabling this option may lead to badly anti-aliased labels on the edges of -+# a graph (i.e. they become hard to read). -+ -+DOT_TRANSPARENT = NO -+ -+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -+# files in one run (i.e. multiple -o and -T options on the command line). This -+# makes dot run faster, but since only newer versions of dot (>1.8.10) -+# support this, this feature is disabled by default. -+ -+DOT_MULTI_TARGETS = NO -+ -+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -+# generate a legend page explaining the meaning of the various boxes and -+# arrows in the dot generated graphs. -+ -+GENERATE_LEGEND = YES -+ -+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -+# remove the intermediate dot files that are used to generate -+# the various graphs. -+ -+DOT_CLEANUP = YES -diff --git a/qt4/src/Mainpage.dox b/qt4/src/Mainpage.dox -new file mode 100644 -index 00000000..30398c3d ---- /dev/null -+++ b/qt4/src/Mainpage.dox -@@ -0,0 +1,85 @@ -+/** -+@mainpage The Poppler Qt4 interface library -+ -+The %Poppler Qt4 interface library, libpoppler-qt4, is a library that -+allows Qt4 programmers to easily load and render PDF files. The -+%Poppler Qt4 interface library uses poppler internally to do its job, -+but the Qt4 programmer will never have to worry about poppler -+internals. -+ -+ -+@section help Current Status -+ -+The %Poppler Qt4 interface library is quite stable and working. -+ -+@section refimpl Example Programs -+ -+Examples programs can be found in the qt4/test directory. The %Poppler -+Qt4 interface library is also used in the KDE's -+document viewer Okular. The source files -+for Okular's PDF plugin (%Poppler-based) can be found on the git server -+of the KDE project, under -+this -+URL. -+ -+ -+@section req How to use the Poppler Qt4 interface library in three easy steps -+ -+Programmer who would like to use the %Poppler Qt4 interface library -+simply need to add the following line to their C++ source files: -+ -+@code -+#include -+@endcode -+ -+A PDF document can then be loaded as follows: -+@code -+QString filename; -+ -+Poppler::Document* document = Poppler::Document::load(filename); -+if (!document || document->isLocked()) { -+ -+ // ... error message .... -+ -+ delete document; -+ return; -+} -+@endcode -+ -+Pages can be rendered to QImages with the following commands: -+ -+@code -+// Paranoid safety check -+if (document == 0) { -+ // ... error message ... -+ return; -+} -+ -+// Access page of the PDF file -+Poppler::Page* pdfPage = document->page(pageNumber); // Document starts at page 0 -+if (pdfPage == 0) { -+ // ... error message ... -+ return; -+} -+ -+// Generate a QImage of the rendered page -+QImage image = pdfPage->renderToImage(xres, yres, x, y, width, height); -+if (image.isNull()) { -+ // ... error message ... -+ return; -+} -+ -+// ... use image ... -+ -+// after the usage, the page must be deleted -+delete pdfPage; -+@endcode -+ -+Finally, don't forget to destroy the document: -+ -+@code -+delete document; -+@endcode -+ */ -+ -diff --git a/qt4/src/poppler-annotation-helper.h b/qt4/src/poppler-annotation-helper.h -new file mode 100644 -index 00000000..3150569c ---- /dev/null -+++ b/qt4/src/poppler-annotation-helper.h -@@ -0,0 +1,183 @@ -+/* poppler-annotation-helper.h: qt interface to poppler -+ * Copyright (C) 2006, 2008, 2017, Albert Astals Cid -+ * Copyright (C) 2008, Pino Toscano -+ * Copyright (C) 2012, Fabio D'Urso -+ * Adapting code from -+ * Copyright (C) 2004 by Enrico Ros -+ * -+ * 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 -+ -+#include -+ -+#include -+ -+class QColor; -+ -+class AnnotColor; -+ -+namespace Poppler { -+ -+class XPDFReader -+{ -+ public: -+ // find named symbol and parse it -+ static inline void lookupName( Dict *, char *, QString & dest ); -+ static inline void lookupString( Dict *, char *, QString & dest ); -+ static inline void lookupBool( Dict *, char *, bool & dest ); -+ static inline void lookupInt( Dict *, char *, int & dest ); -+ static inline void lookupNum( Dict *, char *, double & dest ); -+ static inline int lookupNumArray( Dict *, char *, double * dest, int len ); -+ static inline void lookupColor( Dict *, char *, QColor & color ); -+ static inline void lookupIntRef( Dict *, char *, int & dest ); -+ static inline void lookupDate( Dict *, char *, QDateTime & dest ); -+ // transform from user coords to normalized ones using the matrix M -+ static inline void transform( double * M, double x, double y, QPointF &res ); -+ static inline void invTransform( double * M, const QPointF &p, double &x, double &y ); -+}; -+ -+void XPDFReader::lookupName( Dict * dict, char * type, QString & dest ) -+{ -+ Object nameObj = dict->lookup( type ); -+ if ( nameObj.isNull() ) -+ return; -+ if ( nameObj.isName() ) -+ dest = nameObj.getName(); -+ else -+ qDebug() << type << " is not Name." << endl; -+} -+ -+void XPDFReader::lookupString( Dict * dict, char * type, QString & dest ) -+{ -+ Object stringObj = dict->lookup( type ); -+ if ( stringObj.isNull() ) -+ return; -+ if ( stringObj.isString() ) -+ dest = stringObj.getString()->c_str(); -+ else -+ qDebug() << type << " is not String." << endl; -+} -+ -+void XPDFReader::lookupBool( Dict * dict, char * type, bool & dest ) -+{ -+ Object boolObj = dict->lookup( type ); -+ if ( boolObj.isNull() ) -+ return; -+ if ( boolObj.isBool() ) -+ dest = boolObj.getBool() == true; -+ else -+ qDebug() << type << " is not Bool." << endl; -+} -+ -+void XPDFReader::lookupInt( Dict * dict, char * type, int & dest ) -+{ -+ Object intObj = dict->lookup( type ); -+ if ( intObj.isNull() ) -+ return; -+ if ( intObj.isInt() ) -+ dest = intObj.getInt(); -+ else -+ qDebug() << type << " is not Int." << endl; -+} -+ -+void XPDFReader::lookupNum( Dict * dict, char * type, double & dest ) -+{ -+ Object numObj = dict->lookup( type ); -+ if ( numObj.isNull() ) -+ return; -+ if ( numObj.isNum() ) -+ dest = numObj.getNum(); -+ else -+ qDebug() << type << " is not Num." << endl; -+} -+ -+int XPDFReader::lookupNumArray( Dict * dict, char * type, double * dest, int len ) -+{ -+ Object arrObj = dict->lookup( type ); -+ if ( arrObj.isNull() ) -+ return 0; -+ if ( arrObj.isArray() ) -+ { -+ len = qMin( len, arrObj.arrayGetLength() ); -+ for ( int i = 0; i < len; i++ ) -+ { -+ Object numObj = arrObj.arrayGet( i ); -+ dest[i] = numObj.getNum(); -+ } -+ } -+ else -+ { -+ len = 0; -+ qDebug() << type << "is not Array." << endl; -+ } -+ return len; -+} -+ -+void XPDFReader::lookupColor( Dict * dict, char * type, QColor & dest ) -+{ -+ double c[3]; -+ if ( XPDFReader::lookupNumArray( dict, type, c, 3 ) == 3 ) -+ dest = QColor( (int)(c[0]*255.0), (int)(c[1]*255.0), (int)(c[2]*255.0)); -+} -+ -+void XPDFReader::lookupIntRef( Dict * dict, char * type, int & dest ) -+{ -+ Object refObj = dict->lookupNF( type ).copy(); -+ if ( refObj.isNull() ) -+ return; -+ if ( refObj.isRef() ) -+ dest = refObj.getRefNum(); -+ else -+ qDebug() << type << " is not Ref." << endl; -+} -+ -+void XPDFReader::lookupDate( Dict * dict, char * type, QDateTime & dest ) -+{ -+ Object dateObj = dict->lookup( type ); -+ if ( dateObj.isNull() ) -+ return; -+ if ( dateObj.isString() ) -+ { -+ dest = convertDate( dateObj.getString()->c_str() ); -+ } -+ else -+ qDebug() << type << " is not Date" << endl; -+} -+ -+void XPDFReader::transform( double * M, double x, double y, QPointF &res ) -+{ -+ res.setX( M[0] * x + M[2] * y + M[4] ); -+ res.setY( M[1] * x + M[3] * y + M[5] ); -+} -+ -+void XPDFReader::invTransform( double * M, const QPointF &p, double &x, double &y ) -+{ -+ const double det = M[0]*M[3] - M[1]*M[2]; -+ Q_ASSERT(det != 0); -+ -+ const double invM[4] = { M[3]/det, -M[1]/det, -M[2]/det, M[0]/det }; -+ const double xt = p.x() - M[4]; -+ const double yt = p.y() - M[5]; -+ -+ x = invM[0] * xt + invM[2] * yt; -+ y = invM[1] * xt + invM[3] * yt; -+} -+ -+QColor convertAnnotColor( const AnnotColor *color ); -+std::unique_ptr convertQColor( const QColor &c ); -+ -+} -diff --git a/qt4/src/poppler-annotation-private.h b/qt4/src/poppler-annotation-private.h -new file mode 100644 -index 00000000..b530e2f2 ---- /dev/null -+++ b/qt4/src/poppler-annotation-private.h -@@ -0,0 +1,112 @@ -+/* poppler-annotation-private.h: qt interface to poppler -+ * Copyright (C) 2007, Pino Toscano -+ * Copyright (C) 2012, Tobias Koenig -+ * Copyright (C) 2012, 2013 Fabio D'Urso -+ * Copyright (C) 2012, 2014, Albert Astals Cid -+ * -+ * 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_ANNOTATION_PRIVATE_H_ -+#define _POPPLER_ANNOTATION_PRIVATE_H_ -+ -+#include -+#include -+#include -+ -+#include "poppler-annotation.h" -+ -+#include -+ -+class Annot; -+class AnnotPath; -+class Link; -+class Page; -+class PDFRectangle; -+ -+namespace Poppler -+{ -+class DocumentData; -+ -+class AnnotationPrivate : public QSharedData -+{ -+ public: -+ AnnotationPrivate(); -+ virtual ~AnnotationPrivate(); -+ -+ void addRevision(Annotation *ann, Annotation::RevScope scope, Annotation::RevType type); -+ -+ /* Returns an Annotation of the right subclass whose d_ptr points to -+ * this AnnotationPrivate */ -+ virtual Annotation * makeAlias() = 0; -+ -+ /* properties: contents related */ -+ QString author; -+ QString contents; -+ QString uniqueName; -+ QDateTime modDate; // before or equal to currentDateTime() -+ QDateTime creationDate; // before or equal to modifyDate -+ -+ /* properties: look/interaction related */ -+ int flags; -+ QRectF boundary; -+ -+ /* style and popup */ -+ Annotation::Style style; -+ Annotation::Popup popup; -+ -+ /* revisions */ -+ Annotation::RevScope revisionScope; -+ Annotation::RevType revisionType; -+ QList revisions; -+ -+ /* After this call, the Annotation object will behave like a wrapper for -+ * the specified Annot object. All cached values are discarded */ -+ void tieToNativeAnnot(Annot *ann, ::Page *page, DocumentData *doc); -+ -+ /* Creates a new Annot object on the specified page, flushes current -+ * values to that object and ties this Annotation to that object */ -+ virtual Annot* createNativeAnnot(::Page *destPage, DocumentData *doc) = 0; -+ -+ /* Inited to 0 (i.e. untied annotation) */ -+ Annot *pdfAnnot; -+ ::Page *pdfPage; -+ DocumentData * parentDoc; -+ -+ /* The following helpers only work if pdfPage is set */ -+ void flushBaseAnnotationProperties(); -+ void fillNormalizationMTX(double MTX[6], int pageRotation) const; -+ void fillTransformationMTX(double MTX[6]) const; -+ QRectF fromPdfRectangle(const PDFRectangle &r) const; -+ PDFRectangle boundaryToPdfRectangle(const QRectF &r, int flags) const; -+ AnnotPath * toAnnotPath(const QLinkedList &l) const; -+ -+ /* Scan page for annotations, parentId=0 searches for root annotations, subtypes empty means all subtypes */ -+ static QList findAnnotations(::Page *pdfPage, DocumentData *doc, const QSet &subtypes, int parentId = 0); -+ -+ /* Add given annotation to given page */ -+ static void addAnnotationToPage(::Page *pdfPage, DocumentData *doc, const Annotation * ann); -+ -+ /* Remove annotation from page and destroy ann */ -+ static void removeAnnotationFromPage(::Page *pdfPage, const Annotation * ann); -+ -+ Ref pdfObjectReference() const; -+ -+ Link* additionalAction( Annotation::AdditionalActionType type ) const; -+}; -+ -+} -+ -+#endif -diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc -new file mode 100644 -index 00000000..8a7f60b1 ---- /dev/null -+++ b/qt4/src/poppler-annotation.cc -@@ -0,0 +1,5118 @@ -+/* poppler-annotation.cc: qt interface to poppler -+ * Copyright (C) 2006, 2009, 2012-2015 Albert Astals Cid -+ * Copyright (C) 2006, 2008, 2010 Pino Toscano -+ * Copyright (C) 2012, Guillermo A. Amaral B. -+ * Copyright (C) 2012-2014 Fabio D'Urso -+ * Copyright (C) 2012, 2015, Tobias Koenig -+ * Adapting code from -+ * Copyright (C) 2004 by Enrico Ros -+ * -+ * 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. -+ */ -+ -+// qt/kde includes -+#include -+#include -+#include -+#include -+#include -+ -+// local includes -+#include "poppler-annotation.h" -+#include "poppler-link.h" -+#include "poppler-qt4.h" -+#include "poppler-annotation-helper.h" -+#include "poppler-annotation-private.h" -+#include "poppler-page-private.h" -+#include "poppler-private.h" -+ -+// poppler includes -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Almost all getters directly query the underlying poppler annotation, with -+ * the exceptions of link, file attachment, sound, movie and screen annotations, -+ * Whose data retrieval logic has not been moved yet. Their getters return -+ * static data set at creation time by findAnnotations -+ */ -+ -+namespace Poppler { -+ -+//BEGIN AnnotationUtils implementation -+Annotation * AnnotationUtils::createAnnotation( const QDomElement & annElement ) -+{ -+ // safety check on annotation element -+ if ( !annElement.hasAttribute( "type" ) ) -+ return nullptr; -+ -+ // build annotation of given type -+ Annotation * annotation = nullptr; -+ int typeNumber = annElement.attribute( "type" ).toInt(); -+ switch ( typeNumber ) -+ { -+ case Annotation::AText: -+ annotation = new TextAnnotation( annElement ); -+ break; -+ case Annotation::ALine: -+ annotation = new LineAnnotation( annElement ); -+ break; -+ case Annotation::AGeom: -+ annotation = new GeomAnnotation( annElement ); -+ break; -+ case Annotation::AHighlight: -+ annotation = new HighlightAnnotation( annElement ); -+ break; -+ case Annotation::AStamp: -+ annotation = new StampAnnotation( annElement ); -+ break; -+ case Annotation::AInk: -+ annotation = new InkAnnotation( annElement ); -+ break; -+ case Annotation::ACaret: -+ annotation = new CaretAnnotation( annElement ); -+ break; -+ } -+ -+ // return created annotation -+ return annotation; -+} -+ -+void AnnotationUtils::storeAnnotation( const Annotation * ann, QDomElement & annElement, -+ QDomDocument & document ) -+{ -+ // save annotation's type as element's attribute -+ annElement.setAttribute( "type", (uint)ann->subType() ); -+ -+ // append all annotation data as children of this node -+ ann->store( annElement, document ); -+} -+ -+QDomElement AnnotationUtils::findChildElement( const QDomNode & parentNode, -+ const QString & name ) -+{ -+ // loop through the whole children and return a 'name' named element -+ QDomNode subNode = parentNode.firstChild(); -+ while( subNode.isElement() ) -+ { -+ QDomElement element = subNode.toElement(); -+ if ( element.tagName() == name ) -+ return element; -+ subNode = subNode.nextSibling(); -+ } -+ // if the name can't be found, return a dummy null element -+ return QDomElement(); -+} -+//END AnnotationUtils implementation -+ -+ -+//BEGIN Annotation implementation -+AnnotationPrivate::AnnotationPrivate() -+ : flags( 0 ), revisionScope ( Annotation::Root ), -+ revisionType ( Annotation::None ), pdfAnnot ( nullptr ), pdfPage ( nullptr ), -+ parentDoc ( nullptr ) -+{ -+} -+ -+void AnnotationPrivate::addRevision( Annotation *ann, Annotation::RevScope scope, Annotation::RevType type ) -+{ -+ /* Since ownership stays with the caller, create an alias of ann */ -+ revisions.append( ann->d_ptr->makeAlias() ); -+ -+ /* Set revision properties */ -+ revisionScope = scope; -+ revisionType = type; -+} -+ -+AnnotationPrivate::~AnnotationPrivate() -+{ -+ // Delete all children revisions -+ qDeleteAll( revisions ); -+ -+ // Release Annot object -+ if (pdfAnnot) -+ pdfAnnot->decRefCnt(); -+} -+ -+void AnnotationPrivate::tieToNativeAnnot(Annot *ann, ::Page *page, Poppler::DocumentData * doc) -+{ -+ if (pdfAnnot) -+ { -+ error(errIO, -1, "Annotation is already tied"); -+ return; -+ } -+ -+ pdfAnnot = ann; -+ pdfPage = page; -+ parentDoc = doc; -+ -+ pdfAnnot->incRefCnt(); -+} -+ -+/* This method is called when a new annotation is created, after pdfAnnot and -+ * pdfPage have been set */ -+void AnnotationPrivate::flushBaseAnnotationProperties() -+{ -+ Q_ASSERT ( pdfPage ); -+ -+ Annotation *q = makeAlias(); // Setters are defined in the public class -+ -+ // Since pdfAnnot has been set, this calls will write in the Annot object -+ q->setAuthor(author); -+ q->setContents(contents); -+ q->setUniqueName(uniqueName); -+ q->setModificationDate(modDate); -+ q->setCreationDate(creationDate); -+ q->setFlags(flags); -+ //q->setBoundary(boundary); -- already set by subclass-specific code -+ q->setStyle(style); -+ q->setPopup(popup); -+ -+ // Flush revisions -+ foreach (Annotation *r, revisions) -+ { -+ // TODO: Flush revision -+ delete r; // Object is no longer needed -+ } -+ -+ delete q; -+ -+ // Clear some members to save memory -+ author.clear(); -+ contents.clear(); -+ uniqueName.clear(); -+ revisions.clear(); -+} -+ -+// Returns matrix to convert from user space coords (oriented according to the -+// specified rotation) to normalized coords -+void AnnotationPrivate::fillNormalizationMTX(double MTX[6], int pageRotation) const -+{ -+ Q_ASSERT ( pdfPage ); -+ -+ // build a normalized transform matrix for this page at 100% scale -+ GfxState * gfxState = new GfxState( 72.0, 72.0, pdfPage->getCropBox(), pageRotation, true ); -+ const double * gfxCTM = gfxState->getCTM(); -+ -+ double w = pdfPage->getCropWidth(); -+ double h = pdfPage->getCropHeight(); -+ -+ // Swap width and height if the page is rotated landscape or seascape -+ if ( pageRotation == 90 || pageRotation == 270 ) -+ { -+ double t = w; -+ w = h; -+ h = t; -+ } -+ -+ for ( int i = 0; i < 6; i+=2 ) -+ { -+ MTX[i] = gfxCTM[i] / w; -+ MTX[i+1] = gfxCTM[i+1] / h; -+ } -+ delete gfxState; -+} -+ -+// Returns matrix to convert from user space coords (i.e. those that are stored -+// in the PDF file) to normalized coords (i.e. those that we expose to clients). -+// This method also applies a rotation around the top-left corner if the -+// FixedRotation flag is set. -+void AnnotationPrivate::fillTransformationMTX(double MTX[6]) const -+{ -+ Q_ASSERT ( pdfPage ); -+ Q_ASSERT ( pdfAnnot ); -+ -+ const int pageRotate = pdfPage->getRotate(); -+ -+ if ( pageRotate == 0 || ( pdfAnnot->getFlags() & Annot::flagNoRotate ) == 0 ) -+ { -+ // Use the normalization matrix for this page's rotation -+ fillNormalizationMTX( MTX, pageRotate ); -+ } -+ else -+ { -+ // Clients expect coordinates relative to this page's rotation, but -+ // FixedRotation annotations internally use unrotated coordinates: -+ // construct matrix to both normalize and rotate coordinates using the -+ // top-left corner as rotation pivot -+ -+ double MTXnorm[6]; -+ fillNormalizationMTX( MTXnorm, pageRotate ); -+ -+ QTransform transform( MTXnorm[0], MTXnorm[1], MTXnorm[2], -+ MTXnorm[3], MTXnorm[4], MTXnorm[5] ); -+ transform.translate( +pdfAnnot->getXMin(), +pdfAnnot->getYMax() ); -+ transform.rotate( pageRotate ); -+ transform.translate( -pdfAnnot->getXMin(), -pdfAnnot->getYMax() ); -+ -+ MTX[0] = transform.m11(); -+ MTX[1] = transform.m12(); -+ MTX[2] = transform.m21(); -+ MTX[3] = transform.m22(); -+ MTX[4] = transform.dx(); -+ MTX[5] = transform.dy(); -+ } -+} -+ -+QRectF AnnotationPrivate::fromPdfRectangle(const PDFRectangle &r) const -+{ -+ double swp, MTX[6]; -+ fillTransformationMTX(MTX); -+ -+ QPointF p1, p2; -+ XPDFReader::transform( MTX, r.x1, r.y1, p1 ); -+ XPDFReader::transform( MTX, r.x2, r.y2, p2 ); -+ -+ double tl_x = p1.x(); -+ double tl_y = p1.y(); -+ double br_x = p2.x(); -+ double br_y = p2.y(); -+ -+ if (tl_x > br_x) -+ { -+ swp = tl_x; -+ tl_x = br_x; -+ br_x = swp; -+ } -+ -+ if (tl_y > br_y) -+ { -+ swp = tl_y; -+ tl_y = br_y; -+ br_y = swp; -+ } -+ -+ return QRectF( QPointF(tl_x,tl_y) , QPointF(br_x,br_y) ); -+} -+ -+// This function converts a boundary QRectF in normalized coords to a -+// PDFRectangle in user coords. If the FixedRotation flag is set, this function -+// also applies a rotation around the top-left corner: it's the inverse of -+// the transformation produced by fillTransformationMTX, but we can't use -+// fillTransformationMTX here because it relies on the native annotation -+// object's boundary rect to be already set up. -+PDFRectangle AnnotationPrivate::boundaryToPdfRectangle(const QRectF &r, int flags) const -+{ -+ Q_ASSERT ( pdfPage ); -+ -+ const int pageRotate = pdfPage->getRotate(); -+ -+ double MTX[6]; -+ fillNormalizationMTX( MTX, pageRotate ); -+ -+ double tl_x, tl_y, br_x, br_y, swp; -+ XPDFReader::invTransform( MTX, r.topLeft(), tl_x, tl_y ); -+ XPDFReader::invTransform( MTX, r.bottomRight(), br_x, br_y ); -+ -+ if (tl_x > br_x) -+ { -+ swp = tl_x; -+ tl_x = br_x; -+ br_x = swp; -+ } -+ -+ if (tl_y > br_y) -+ { -+ swp = tl_y; -+ tl_y = br_y; -+ br_y = swp; -+ } -+ -+ const int rotationFixUp = ( flags & Annotation::FixedRotation ) ? pageRotate : 0; -+ const double width = br_x - tl_x; -+ const double height = br_y - tl_y; -+ -+ if ( rotationFixUp == 0 ) -+ return PDFRectangle(tl_x, tl_y, br_x, br_y); -+ else if ( rotationFixUp == 90 ) -+ return PDFRectangle(tl_x, tl_y - width, tl_x + height, tl_y); -+ else if ( rotationFixUp == 180 ) -+ return PDFRectangle(br_x, tl_y - height, br_x + width, tl_y); -+ else // rotationFixUp == 270 -+ return PDFRectangle(br_x, br_y - width, br_x + height, br_y); -+} -+ -+AnnotPath * AnnotationPrivate::toAnnotPath(const QLinkedList &list) const -+{ -+ const int count = list.size(); -+ std::vector ac; -+ ac.reserve(count); -+ -+ double MTX[6]; -+ fillTransformationMTX(MTX); -+ -+ foreach (const QPointF &p, list) -+ { -+ double x, y; -+ XPDFReader::invTransform( MTX, p, x, y ); -+ ac.emplace_back(x, y); -+ } -+ -+ return new AnnotPath(std::move(ac)); -+} -+ -+QList AnnotationPrivate::findAnnotations(::Page *pdfPage, DocumentData *doc, const QSet &subtypes, int parentID) -+{ -+ Annots* annots = pdfPage->getAnnots(); -+ const uint numAnnotations = annots->getNumAnnots(); -+ if ( numAnnotations == 0 ) -+ { -+ return QList(); -+ } -+ -+ const bool wantTextAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AText); -+ const bool wantLineAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::ALine); -+ const bool wantGeomAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AGeom); -+ const bool wantHighlightAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AHighlight); -+ const bool wantStampAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AStamp); -+ const bool wantInkAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AInk); -+ const bool wantLinkAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::ALink); -+ const bool wantCaretAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::ACaret); -+ const bool wantFileAttachmentAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AFileAttachment); -+ const bool wantSoundAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::ASound); -+ const bool wantMovieAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AMovie); -+ const bool wantScreenAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AScreen); -+ const bool wantWidgetAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AWidget); -+ -+ // Create Annotation objects and tie to their native Annot -+ QList res; -+ for ( uint j = 0; j < numAnnotations; j++ ) -+ { -+ // get the j-th annotation -+ Annot * ann = annots->getAnnot( j ); -+ if ( !ann ) -+ { -+ error(errInternal, -1, "Annot {0:ud} is null", j); -+ continue; -+ } -+ -+ // Check parent annotation -+ AnnotMarkup * markupann = dynamic_cast< AnnotMarkup * >( ann ); -+ if (!markupann) -+ { -+ // Assume it's a root annotation, and skip if user didn't request it -+ if (parentID != 0) -+ continue; -+ } -+ else if (markupann->getInReplyToID() != parentID) -+ continue; -+ -+ /* Create Annotation of the right subclass */ -+ Annotation * annotation = nullptr; -+ Annot::AnnotSubtype subType = ann->getType(); -+ -+ switch ( subType ) -+ { -+ case Annot::typeText: -+ if (!wantTextAnnotations) -+ continue; -+ annotation = new TextAnnotation(TextAnnotation::Linked); -+ break; -+ case Annot::typeFreeText: -+ if (!wantTextAnnotations) -+ continue; -+ annotation = new TextAnnotation(TextAnnotation::InPlace); -+ break; -+ case Annot::typeLine: -+ if (!wantLineAnnotations) -+ continue; -+ annotation = new LineAnnotation(LineAnnotation::StraightLine); -+ break; -+ case Annot::typePolygon: -+ case Annot::typePolyLine: -+ if (!wantLineAnnotations) -+ continue; -+ annotation = new LineAnnotation(LineAnnotation::Polyline); -+ break; -+ case Annot::typeSquare: -+ case Annot::typeCircle: -+ if (!wantGeomAnnotations) -+ continue; -+ annotation = new GeomAnnotation(); -+ break; -+ case Annot::typeHighlight: -+ case Annot::typeUnderline: -+ case Annot::typeSquiggly: -+ case Annot::typeStrikeOut: -+ if (!wantHighlightAnnotations) -+ continue; -+ annotation = new HighlightAnnotation(); -+ break; -+ case Annot::typeStamp: -+ if (!wantStampAnnotations) -+ continue; -+ annotation = new StampAnnotation(); -+ break; -+ case Annot::typeInk: -+ if (!wantInkAnnotations) -+ continue; -+ annotation = new InkAnnotation(); -+ break; -+ case Annot::typeLink: /* TODO: Move logic to getters */ -+ { -+ if (!wantLinkAnnotations) -+ continue; -+ // parse Link params -+ AnnotLink * linkann = static_cast< AnnotLink * >( ann ); -+ LinkAnnotation * l = new LinkAnnotation(); -+ annotation = l; -+ -+ // -> hlMode -+ l->setLinkHighlightMode( (LinkAnnotation::HighlightMode)linkann->getLinkEffect() ); -+ -+ // -> link region -+ // TODO -+ -+ // reading link action -+ if ( linkann->getAction() ) -+ { -+ Link * popplerLink = PageData::convertLinkActionToLink( linkann->getAction(), doc, QRectF() ); -+ if ( popplerLink ) -+ { -+ l->setLinkDestination( popplerLink ); -+ } -+ } -+ break; -+ } -+ case Annot::typeCaret: -+ if (!wantCaretAnnotations) -+ continue; -+ annotation = new CaretAnnotation(); -+ break; -+ case Annot::typeFileAttachment: /* TODO: Move logic to getters */ -+ { -+ if (!wantFileAttachmentAnnotations) -+ continue; -+ AnnotFileAttachment * attachann = static_cast< AnnotFileAttachment * >( ann ); -+ FileAttachmentAnnotation * f = new FileAttachmentAnnotation(); -+ annotation = f; -+ // -> fileIcon -+ f->setFileIconName( QString::fromLatin1( attachann->getName()->c_str() ) ); -+ // -> embeddedFile -+ FileSpec *filespec = new FileSpec( attachann->getFile() ); -+ f->setEmbeddedFile( new EmbeddedFile( *new EmbeddedFileData( filespec ) ) ); -+ break; -+ } -+ case Annot::typeSound: /* TODO: Move logic to getters */ -+ { -+ if (!wantSoundAnnotations) -+ continue; -+ AnnotSound * soundann = static_cast< AnnotSound * >( ann ); -+ SoundAnnotation * s = new SoundAnnotation(); -+ annotation = s; -+ -+ // -> soundIcon -+ s->setSoundIconName( QString::fromLatin1( soundann->getName()->c_str() ) ); -+ // -> sound -+ s->setSound( new SoundObject( soundann->getSound() ) ); -+ break; -+ } -+ case Annot::typeMovie: /* TODO: Move logic to getters */ -+ { -+ if (!wantMovieAnnotations) -+ continue; -+ AnnotMovie * movieann = static_cast< AnnotMovie * >( ann ); -+ MovieAnnotation * m = new MovieAnnotation(); -+ annotation = m; -+ -+ // -> movie -+ MovieObject *movie = new MovieObject( movieann ); -+ m->setMovie( movie ); -+ // -> movieTitle -+ const GooString * movietitle = movieann->getTitle(); -+ if ( movietitle ) -+ m->setMovieTitle( QString::fromLatin1( movietitle->c_str() ) ); -+ break; -+ } -+ case Annot::typeScreen: -+ { -+ if (!wantScreenAnnotations) -+ continue; -+ AnnotScreen * screenann = static_cast< AnnotScreen * >( ann ); -+ if (!screenann->getAction()) -+ continue; -+ ScreenAnnotation * s = new ScreenAnnotation(); -+ annotation = s; -+ -+ // -> screen -+ Link * popplerLink = PageData::convertLinkActionToLink( screenann->getAction(), doc, QRectF() ); -+ s->setAction( static_cast(popplerLink) ); -+ -+ // -> screenTitle -+ const GooString * screentitle = screenann->getTitle(); -+ if ( screentitle ) -+ s->setScreenTitle( UnicodeParsedString( screentitle ) ); -+ break; -+ } -+ case Annot::typePopup: -+ continue; // popups are parsed by Annotation's window() getter -+ case Annot::typeUnknown: -+ continue; // special case for ignoring unknown annotations -+ case Annot::typeWidget: -+ if (!wantWidgetAnnotations) -+ continue; -+ annotation = new WidgetAnnotation(); -+ break; -+ case Annot::typeRichMedia: -+ { -+ const AnnotRichMedia * annotRichMedia = static_cast< AnnotRichMedia * >( ann ); -+ -+ RichMediaAnnotation *richMediaAnnotation = new RichMediaAnnotation; -+ -+ const AnnotRichMedia::Settings *annotSettings = annotRichMedia->getSettings(); -+ if ( annotSettings ) { -+ RichMediaAnnotation::Settings *settings = new RichMediaAnnotation::Settings; -+ -+ if ( annotSettings->getActivation() ) { -+ RichMediaAnnotation::Activation *activation = new RichMediaAnnotation::Activation; -+ -+ switch ( annotSettings->getActivation()->getCondition() ) -+ { -+ case AnnotRichMedia::Activation::conditionPageOpened: -+ activation->setCondition( RichMediaAnnotation::Activation::PageOpened ); -+ break; -+ case AnnotRichMedia::Activation::conditionPageVisible: -+ activation->setCondition( RichMediaAnnotation::Activation::PageVisible ); -+ break; -+ case AnnotRichMedia::Activation::conditionUserAction: -+ activation->setCondition( RichMediaAnnotation::Activation::UserAction ); -+ break; -+ } -+ -+ settings->setActivation( activation ); -+ } -+ -+ if ( annotSettings->getDeactivation() ) { -+ RichMediaAnnotation::Deactivation *deactivation = new RichMediaAnnotation::Deactivation; -+ -+ switch ( annotSettings->getDeactivation()->getCondition() ) -+ { -+ case AnnotRichMedia::Deactivation::conditionPageClosed: -+ deactivation->setCondition( RichMediaAnnotation::Deactivation::PageClosed ); -+ break; -+ case AnnotRichMedia::Deactivation::conditionPageInvisible: -+ deactivation->setCondition( RichMediaAnnotation::Deactivation::PageInvisible ); -+ break; -+ case AnnotRichMedia::Deactivation::conditionUserAction: -+ deactivation->setCondition( RichMediaAnnotation::Deactivation::UserAction ); -+ break; -+ } -+ -+ settings->setDeactivation( deactivation ); -+ } -+ -+ richMediaAnnotation->setSettings( settings ); -+ } -+ -+ const AnnotRichMedia::Content *annotContent = annotRichMedia->getContent(); -+ if ( annotContent ) { -+ RichMediaAnnotation::Content *content = new RichMediaAnnotation::Content; -+ -+ const int configurationsCount = annotContent->getConfigurationsCount(); -+ if ( configurationsCount > 0 ) { -+ QList< RichMediaAnnotation::Configuration* > configurations; -+ -+ for ( int i = 0; i < configurationsCount; ++i ) { -+ const AnnotRichMedia::Configuration *annotConfiguration = annotContent->getConfiguration( i ); -+ if ( !annotConfiguration ) -+ continue; -+ -+ RichMediaAnnotation::Configuration *configuration = new RichMediaAnnotation::Configuration; -+ -+ if ( annotConfiguration->getName() ) -+ configuration->setName( UnicodeParsedString( annotConfiguration->getName() ) ); -+ -+ switch ( annotConfiguration->getType() ) -+ { -+ case AnnotRichMedia::Configuration::type3D: -+ configuration->setType( RichMediaAnnotation::Configuration::Type3D ); -+ break; -+ case AnnotRichMedia::Configuration::typeFlash: -+ configuration->setType( RichMediaAnnotation::Configuration::TypeFlash ); -+ break; -+ case AnnotRichMedia::Configuration::typeSound: -+ configuration->setType( RichMediaAnnotation::Configuration::TypeSound ); -+ break; -+ case AnnotRichMedia::Configuration::typeVideo: -+ configuration->setType( RichMediaAnnotation::Configuration::TypeVideo ); -+ break; -+ } -+ -+ const int instancesCount = annotConfiguration->getInstancesCount(); -+ if ( instancesCount > 0 ) { -+ QList< RichMediaAnnotation::Instance* > instances; -+ -+ for ( int j = 0; j < instancesCount; ++j ) { -+ const AnnotRichMedia::Instance *annotInstance = annotConfiguration->getInstance( j ); -+ if ( !annotInstance ) -+ continue; -+ -+ RichMediaAnnotation::Instance *instance = new RichMediaAnnotation::Instance; -+ -+ switch ( annotInstance->getType() ) -+ { -+ case AnnotRichMedia::Instance::type3D: -+ instance->setType( RichMediaAnnotation::Instance::Type3D ); -+ break; -+ case AnnotRichMedia::Instance::typeFlash: -+ instance->setType( RichMediaAnnotation::Instance::TypeFlash ); -+ break; -+ case AnnotRichMedia::Instance::typeSound: -+ instance->setType( RichMediaAnnotation::Instance::TypeSound ); -+ break; -+ case AnnotRichMedia::Instance::typeVideo: -+ instance->setType( RichMediaAnnotation::Instance::TypeVideo ); -+ break; -+ } -+ -+ const AnnotRichMedia::Params *annotParams = annotInstance->getParams(); -+ if ( annotParams ) { -+ RichMediaAnnotation::Params *params = new RichMediaAnnotation::Params; -+ -+ if ( annotParams->getFlashVars() ) -+ params->setFlashVars( UnicodeParsedString( annotParams->getFlashVars() ) ); -+ -+ instance->setParams( params ); -+ } -+ -+ instances.append( instance ); -+ } -+ -+ configuration->setInstances( instances ); -+ } -+ -+ configurations.append( configuration ); -+ } -+ -+ content->setConfigurations( configurations ); -+ } -+ -+ const int assetsCount = annotContent->getAssetsCount(); -+ if ( assetsCount > 0 ) { -+ QList< RichMediaAnnotation::Asset* > assets; -+ -+ for ( int i = 0; i < assetsCount; ++i ) { -+ const AnnotRichMedia::Asset *annotAsset = annotContent->getAsset( i ); -+ if ( !annotAsset ) -+ continue; -+ -+ RichMediaAnnotation::Asset *asset = new RichMediaAnnotation::Asset; -+ -+ if ( annotAsset->getName() ) -+ asset->setName( UnicodeParsedString( annotAsset->getName() ) ); -+ -+ FileSpec *fileSpec = new FileSpec( annotAsset->getFileSpec() ); -+ asset->setEmbeddedFile( new EmbeddedFile( *new EmbeddedFileData( fileSpec ) ) ); -+ -+ assets.append( asset ); -+ } -+ -+ content->setAssets( assets ); -+ } -+ -+ richMediaAnnotation->setContent( content ); -+ } -+ -+ annotation = richMediaAnnotation; -+ -+ break; -+ } -+ default: -+ { -+#define CASE_FOR_TYPE( thetype ) \ -+ case Annot::type ## thetype: \ -+ error(errUnimplemented, -1, "Annotation " #thetype " not supported"); \ -+ break; -+ switch ( subType ) -+ { -+ CASE_FOR_TYPE( PrinterMark ) -+ CASE_FOR_TYPE( TrapNet ) -+ CASE_FOR_TYPE( Watermark ) -+ CASE_FOR_TYPE( 3D ) -+ default: error(errUnimplemented, -1, "Annotation {0:d} not supported", subType); -+ } -+ continue; -+#undef CASE_FOR_TYPE -+ } -+ } -+ -+ annotation->d_ptr->tieToNativeAnnot(ann, pdfPage, doc); -+ res.append(annotation); -+ } -+ -+ return res; -+} -+ -+Ref AnnotationPrivate::pdfObjectReference() const -+{ -+ if (pdfAnnot == nullptr) -+ { -+ const Ref invalid_ref = { -1, -1 }; -+ return invalid_ref; -+ } -+ -+ return pdfAnnot->getRef(); -+} -+ -+Link* AnnotationPrivate::additionalAction( Annotation::AdditionalActionType type ) const -+{ -+ if ( pdfAnnot->getType() != Annot::typeScreen && pdfAnnot->getType() != Annot::typeWidget ) -+ return nullptr; -+ -+ Annot::AdditionalActionsType actionType = Annot::actionCursorEntering; -+ switch ( type ) -+ { -+ case Annotation::CursorEnteringAction: actionType = Annot::actionCursorEntering; break; -+ case Annotation::CursorLeavingAction: actionType = Annot::actionCursorLeaving; break; -+ case Annotation::MousePressedAction: actionType = Annot::actionMousePressed; break; -+ case Annotation::MouseReleasedAction: actionType = Annot::actionMouseReleased; break; -+ case Annotation::FocusInAction: actionType = Annot::actionFocusIn; break; -+ case Annotation::FocusOutAction: actionType = Annot::actionFocusOut; break; -+ case Annotation::PageOpeningAction: actionType = Annot::actionPageOpening; break; -+ case Annotation::PageClosingAction: actionType = Annot::actionPageClosing; break; -+ case Annotation::PageVisibleAction: actionType = Annot::actionPageVisible; break; -+ case Annotation::PageInvisibleAction: actionType = Annot::actionPageInvisible; break; -+ } -+ -+ ::LinkAction *linkAction = nullptr; -+ if ( pdfAnnot->getType() == Annot::typeScreen ) -+ linkAction = static_cast( pdfAnnot )->getAdditionalAction( actionType ); -+ else -+ linkAction = static_cast( pdfAnnot )->getAdditionalAction( actionType ); -+ -+ Link *link = nullptr; -+ -+ if ( linkAction ) -+ link = PageData::convertLinkActionToLink( linkAction, parentDoc, QRectF() ); -+ -+ return link; -+} -+ -+void AnnotationPrivate::addAnnotationToPage(::Page *pdfPage, DocumentData *doc, const Annotation * ann) -+{ -+ if (ann->d_ptr->pdfAnnot != nullptr) -+ { -+ error(errIO, -1, "Annotation is already tied"); -+ return; -+ } -+ -+ // Unimplemented annotations can't be created by the user because their ctor -+ // is private. Therefore, createNativeAnnot will never return 0 -+ Annot *nativeAnnot = ann->d_ptr->createNativeAnnot(pdfPage, doc); -+ Q_ASSERT(nativeAnnot); -+ pdfPage->addAnnot(nativeAnnot); -+} -+ -+void AnnotationPrivate::removeAnnotationFromPage(::Page *pdfPage, const Annotation * ann) -+{ -+ if (ann->d_ptr->pdfAnnot == nullptr) -+ { -+ error(errIO, -1, "Annotation is not tied"); -+ return; -+ } -+ -+ if (ann->d_ptr->pdfPage != pdfPage) -+ { -+ error(errIO, -1, "Annotation doesn't belong to the specified page"); -+ return; -+ } -+ -+ // Remove annotation -+ pdfPage->removeAnnot(ann->d_ptr->pdfAnnot); -+ -+ // Destroy object -+ delete ann; -+} -+ -+class Annotation::Style::Private : public QSharedData -+{ -+ public: -+ Private() -+ : opacity( 1.0 ), width( 1.0 ), lineStyle( Solid ), xCorners( 0.0 ), -+ yCorners( 0.0 ), lineEffect( NoEffect ), effectIntensity( 1.0 ) -+ { -+ dashArray.resize(1); -+ dashArray[0] = 3; -+ } -+ -+ QColor color; -+ double opacity; -+ double width; -+ Annotation::LineStyle lineStyle; -+ double xCorners; -+ double yCorners; -+ QVector dashArray; -+ Annotation::LineEffect lineEffect; -+ double effectIntensity; -+}; -+ -+Annotation::Style::Style() -+ : d ( new Private ) -+{ -+} -+ -+Annotation::Style::Style( const Style &other ) -+ : d( other.d ) -+{ -+} -+ -+Annotation::Style& Annotation::Style::operator=( const Style &other ) -+{ -+ if ( this != &other ) -+ d = other.d; -+ -+ return *this; -+} -+ -+Annotation::Style::~Style() -+{ -+} -+ -+QColor Annotation::Style::color() const -+{ -+ return d->color; -+} -+ -+void Annotation::Style::setColor(const QColor &color) -+{ -+ d->color = color; -+} -+ -+double Annotation::Style::opacity() const -+{ -+ return d->opacity; -+} -+ -+void Annotation::Style::setOpacity(double opacity) -+{ -+ d->opacity = opacity; -+} -+ -+double Annotation::Style::width() const -+{ -+ return d->width; -+} -+ -+void Annotation::Style::setWidth(double width) -+{ -+ d->width = width; -+} -+ -+Annotation::LineStyle Annotation::Style::lineStyle() const -+{ -+ return d->lineStyle; -+} -+ -+void Annotation::Style::setLineStyle(Annotation::LineStyle style) -+{ -+ d->lineStyle = style; -+} -+ -+double Annotation::Style::xCorners() const -+{ -+ return d->xCorners; -+} -+ -+void Annotation::Style::setXCorners(double radius) -+{ -+ d->xCorners = radius; -+} -+ -+double Annotation::Style::yCorners() const -+{ -+ return d->yCorners; -+} -+ -+void Annotation::Style::setYCorners(double radius) -+{ -+ d->yCorners = radius; -+} -+ -+const QVector& Annotation::Style::dashArray() const -+{ -+ return d->dashArray; -+} -+ -+void Annotation::Style::setDashArray(const QVector &array) -+{ -+ d->dashArray = array; -+} -+ -+Annotation::LineEffect Annotation::Style::lineEffect() const -+{ -+ return d->lineEffect; -+} -+ -+void Annotation::Style::setLineEffect(Annotation::LineEffect effect) -+{ -+ d->lineEffect = effect; -+} -+ -+double Annotation::Style::effectIntensity() const -+{ -+ return d->effectIntensity; -+} -+ -+void Annotation::Style::setEffectIntensity(double intens) -+{ -+ d->effectIntensity = intens; -+} -+ -+class Annotation::Popup::Private : public QSharedData -+{ -+ public: -+ Private() -+ : flags( -1 ) {} -+ -+ int flags; -+ QRectF geometry; -+ QString title; -+ QString summary; -+ QString text; -+}; -+ -+Annotation::Popup::Popup() -+ : d ( new Private ) -+{ -+} -+ -+Annotation::Popup::Popup( const Popup &other ) -+ : d( other.d ) -+{ -+} -+ -+Annotation::Popup& Annotation::Popup::operator=( const Popup &other ) -+{ -+ if ( this != &other ) -+ d = other.d; -+ -+ return *this; -+} -+ -+Annotation::Popup::~Popup() -+{ -+} -+ -+int Annotation::Popup::flags() const -+{ -+ return d->flags; -+} -+ -+void Annotation::Popup::setFlags( int flags ) -+{ -+ d->flags = flags; -+} -+ -+QRectF Annotation::Popup::geometry() const -+{ -+ return d->geometry; -+} -+ -+void Annotation::Popup::setGeometry( const QRectF &geom ) -+{ -+ d->geometry = geom; -+} -+ -+QString Annotation::Popup::title() const -+{ -+ return d->title; -+} -+ -+void Annotation::Popup::setTitle( const QString &title ) -+{ -+ d->title = title; -+} -+ -+QString Annotation::Popup::summary() const -+{ -+ return d->summary; -+} -+ -+void Annotation::Popup::setSummary( const QString &summary ) -+{ -+ d->summary = summary; -+} -+ -+QString Annotation::Popup::text() const -+{ -+ return d->text; -+} -+ -+void Annotation::Popup::setText( const QString &text ) -+{ -+ d->text = text; -+} -+ -+Annotation::Annotation( AnnotationPrivate &dd ) -+ : d_ptr( &dd ) -+{ -+ window.width = window.height = 0; -+} -+ -+Annotation::~Annotation() -+{ -+} -+ -+Annotation::Annotation( AnnotationPrivate &dd, const QDomNode &annNode ) -+ : d_ptr( &dd ) -+{ -+ Q_D( Annotation ); -+ -+ window.width = window.height = 0; -+ -+ // get the [base] element of the annotation node -+ QDomElement e = AnnotationUtils::findChildElement( annNode, "base" ); -+ if ( e.isNull() ) -+ return; -+ -+ Style s; -+ Popup w; -+ -+ // parse -contents- attributes -+ if ( e.hasAttribute( "author" ) ) -+ setAuthor(e.attribute( "author" )); -+ if ( e.hasAttribute( "contents" ) ) -+ setContents(e.attribute( "contents" )); -+ if ( e.hasAttribute( "uniqueName" ) ) -+ setUniqueName(e.attribute( "uniqueName" )); -+ if ( e.hasAttribute( "modifyDate" ) ) -+ setModificationDate(QDateTime::fromString( e.attribute( "modifyDate" ) )); -+ if ( e.hasAttribute( "creationDate" ) ) -+ setCreationDate(QDateTime::fromString( e.attribute( "creationDate" ) )); -+ -+ // parse -other- attributes -+ if ( e.hasAttribute( "flags" ) ) -+ setFlags(e.attribute( "flags" ).toInt()); -+ if ( e.hasAttribute( "color" ) ) -+ s.setColor(QColor( e.attribute( "color" ) )); -+ if ( e.hasAttribute( "opacity" ) ) -+ s.setOpacity(e.attribute( "opacity" ).toDouble()); -+ -+ // parse -the-subnodes- (describing Style, Window, Revision(s) structures) -+ // Note: all subnodes if present must be 'attributes complete' -+ QDomNode eSubNode = e.firstChild(); -+ while ( eSubNode.isElement() ) -+ { -+ QDomElement ee = eSubNode.toElement(); -+ eSubNode = eSubNode.nextSibling(); -+ -+ // parse boundary -+ if ( ee.tagName() == "boundary" ) -+ { -+ QRectF brect; -+ brect.setLeft(ee.attribute( "l" ).toDouble()); -+ brect.setTop(ee.attribute( "t" ).toDouble()); -+ brect.setRight(ee.attribute( "r" ).toDouble()); -+ brect.setBottom(ee.attribute( "b" ).toDouble()); -+ setBoundary(brect); -+ } -+ // parse penStyle if not default -+ else if ( ee.tagName() == "penStyle" ) -+ { -+ s.setWidth(ee.attribute( "width" ).toDouble()); -+ s.setLineStyle((LineStyle)ee.attribute( "style" ).toInt()); -+ s.setXCorners(ee.attribute( "xcr" ).toDouble()); -+ s.setYCorners(ee.attribute( "ycr" ).toDouble()); -+ -+ // Try to parse dash array (new format) -+ QVector dashArray; -+ -+ QDomNode eeSubNode = ee.firstChild(); -+ while ( eeSubNode.isElement() ) -+ { -+ QDomElement eee = eeSubNode.toElement(); -+ eeSubNode = eeSubNode.nextSibling(); -+ -+ if ( eee.tagName() != "dashsegm" ) -+ continue; -+ -+ dashArray.append(eee.attribute( "len" ).toDouble()); -+ } -+ -+ // If no segments were found use marks/spaces (old format) -+ if ( dashArray.size() == 0 ) -+ { -+ dashArray.append(ee.attribute( "marks" ).toDouble()); -+ dashArray.append(ee.attribute( "spaces" ).toDouble()); -+ } -+ -+ s.setDashArray(dashArray); -+ } -+ // parse effectStyle if not default -+ else if ( ee.tagName() == "penEffect" ) -+ { -+ s.setLineEffect((LineEffect)ee.attribute( "effect" ).toInt()); -+ s.setEffectIntensity(ee.attribute( "intensity" ).toDouble()); -+ } -+ // parse window if present -+ else if ( ee.tagName() == "window" ) -+ { -+ QRectF geom; -+ geom.setX(ee.attribute( "top" ).toDouble()); -+ geom.setY(ee.attribute( "left" ).toDouble()); -+ -+ if (ee.hasAttribute("widthDouble")) -+ geom.setWidth(ee.attribute( "widthDouble" ).toDouble()); -+ else -+ geom.setWidth(ee.attribute( "width" ).toDouble()); -+ -+ if (ee.hasAttribute("widthDouble")) -+ geom.setHeight(ee.attribute( "heightDouble" ).toDouble()); -+ else -+ geom.setHeight(ee.attribute( "height" ).toDouble()); -+ -+ w.setGeometry(geom); -+ -+ w.setFlags(ee.attribute( "flags" ).toInt()); -+ w.setTitle(ee.attribute( "title" )); -+ w.setSummary(ee.attribute( "summary" )); -+ // parse window subnodes -+ QDomNode winNode = ee.firstChild(); -+ for ( ; winNode.isElement(); winNode = winNode.nextSibling() ) -+ { -+ QDomElement winElement = winNode.toElement(); -+ if ( winElement.tagName() == "text" ) -+ w.setText(winElement.firstChild().toCDATASection().data()); -+ } -+ } -+ } -+ -+ setStyle(s); // assign parsed style -+ setPopup(w); // assign parsed window -+ -+ // get the [revisions] element of the annotation node -+ QDomNode revNode = annNode.firstChild(); -+ for ( ; revNode.isElement(); revNode = revNode.nextSibling() ) -+ { -+ QDomElement revElement = revNode.toElement(); -+ if ( revElement.tagName() != "revision" ) -+ continue; -+ -+ Annotation *reply = AnnotationUtils::createAnnotation( revElement ); -+ -+ if (reply) // if annotation is valid, add as a revision of this annotation -+ { -+ RevScope scope = (RevScope)revElement.attribute( "revScope" ).toInt(); -+ RevType type = (RevType)revElement.attribute( "revType" ).toInt(); -+ d->addRevision(reply, scope, type); -+ delete reply; -+ } -+ } -+} -+ -+void Annotation::storeBaseAnnotationProperties( QDomNode & annNode, QDomDocument & document ) const -+{ -+ // create [base] element of the annotation node -+ QDomElement e = document.createElement( "base" ); -+ annNode.appendChild( e ); -+ -+ const Style s = style(); -+ const Popup w = popup(); -+ -+ // store -contents- attributes -+ if ( !author().isEmpty() ) -+ e.setAttribute( "author", author() ); -+ if ( !contents().isEmpty() ) -+ e.setAttribute( "contents", contents() ); -+ if ( !uniqueName().isEmpty() ) -+ e.setAttribute( "uniqueName", uniqueName() ); -+ if ( modificationDate().isValid() ) -+ e.setAttribute( "modifyDate", modificationDate().toString() ); -+ if ( creationDate().isValid() ) -+ e.setAttribute( "creationDate", creationDate().toString() ); -+ -+ // store -other- attributes -+ if ( flags() ) -+ e.setAttribute( "flags", flags() ); -+ if ( s.color().isValid() ) -+ e.setAttribute( "color", s.color().name() ); -+ if ( s.opacity() != 1.0 ) -+ e.setAttribute( "opacity", QString::number( s.opacity() ) ); -+ -+ // Sub-Node-1 - boundary -+ const QRectF brect = boundary(); -+ QDomElement bE = document.createElement( "boundary" ); -+ e.appendChild( bE ); -+ bE.setAttribute( "l", QString::number( (double)brect.left() ) ); -+ bE.setAttribute( "t", QString::number( (double)brect.top() ) ); -+ bE.setAttribute( "r", QString::number( (double)brect.right() ) ); -+ bE.setAttribute( "b", QString::number( (double)brect.bottom() ) ); -+ -+ // Sub-Node-2 - penStyle -+ const QVector dashArray = s.dashArray(); -+ if ( s.width() != 1 || s.lineStyle() != Solid || s.xCorners() != 0 || -+ s.yCorners() != 0.0 || dashArray.size() != 1 || dashArray[0] != 3 ) -+ { -+ QDomElement psE = document.createElement( "penStyle" ); -+ e.appendChild( psE ); -+ psE.setAttribute( "width", QString::number( s.width() ) ); -+ psE.setAttribute( "style", (int)s.lineStyle() ); -+ psE.setAttribute( "xcr", QString::number( s.xCorners() ) ); -+ psE.setAttribute( "ycr", QString::number( s.yCorners() ) ); -+ -+ int marks = 3, spaces = 0; // Do not break code relying on marks/spaces -+ if (dashArray.size() != 0) -+ marks = (int)dashArray[0]; -+ if (dashArray.size() > 1) -+ spaces = (int)dashArray[1]; -+ -+ psE.setAttribute( "marks", marks ); -+ psE.setAttribute( "spaces", spaces ); -+ -+ foreach (double segm, dashArray) -+ { -+ QDomElement pattE = document.createElement( "dashsegm" ); -+ pattE.setAttribute( "len", QString::number( segm ) ); -+ psE.appendChild(pattE); -+ } -+ } -+ -+ // Sub-Node-3 - penEffect -+ if ( s.lineEffect() != NoEffect || s.effectIntensity() != 1.0 ) -+ { -+ QDomElement peE = document.createElement( "penEffect" ); -+ e.appendChild( peE ); -+ peE.setAttribute( "effect", (int)s.lineEffect() ); -+ peE.setAttribute( "intensity", QString::number( s.effectIntensity() ) ); -+ } -+ -+ // Sub-Node-4 - window -+ if ( w.flags() != -1 || !w.title().isEmpty() || !w.summary().isEmpty() || -+ !w.text().isEmpty() ) -+ { -+ QDomElement wE = document.createElement( "window" ); -+ const QRectF geom = w.geometry(); -+ e.appendChild( wE ); -+ wE.setAttribute( "flags", w.flags() ); -+ wE.setAttribute( "top", QString::number( geom.x() ) ); -+ wE.setAttribute( "left", QString::number( geom.y() ) ); -+ wE.setAttribute( "width", (int)geom.width() ); -+ wE.setAttribute( "height", (int)geom.height() ); -+ wE.setAttribute( "widthDouble", QString::number( geom.width() ) ); -+ wE.setAttribute( "heightDouble", QString::number( geom.height() ) ); -+ wE.setAttribute( "title", w.title() ); -+ wE.setAttribute( "summary", w.summary() ); -+ // store window.text as a subnode, because we need escaped data -+ if ( !w.text().isEmpty() ) -+ { -+ QDomElement escapedText = document.createElement( "text" ); -+ wE.appendChild( escapedText ); -+ QDomCDATASection textCData = document.createCDATASection( w.text() ); -+ escapedText.appendChild( textCData ); -+ } -+ } -+ -+ const QList revs = revisions(); -+ -+ // create [revision] element of the annotation node (if any) -+ if ( revs.isEmpty() ) -+ return; -+ -+ // add all revisions as children of revisions element -+ foreach (const Annotation *rev, revs) -+ { -+ QDomElement r = document.createElement( "revision" ); -+ annNode.appendChild( r ); -+ // set element attributes -+ r.setAttribute( "revScope", (int)rev->revisionScope() ); -+ r.setAttribute( "revType", (int)rev->revisionType() ); -+ // use revision as the annotation element, so fill it up -+ AnnotationUtils::storeAnnotation( rev, r, document ); -+ delete rev; -+ } -+} -+ -+QString Annotation::author() const -+{ -+ Q_D( const Annotation ); -+ -+ if (!d->pdfAnnot) -+ return d->author; -+ -+ const AnnotMarkup *markupann = dynamic_cast(d->pdfAnnot); -+ return markupann ? UnicodeParsedString( markupann->getLabel() ) : QString(); -+} -+ -+void Annotation::setAuthor( const QString &author ) -+{ -+ Q_D( Annotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->author = author; -+ return; -+ } -+ -+ AnnotMarkup *markupann = dynamic_cast(d->pdfAnnot); -+ if (markupann) -+ { -+ GooString *s = QStringToUnicodeGooString(author); -+ markupann->setLabel(s); -+ delete s; -+ } -+} -+ -+QString Annotation::contents() const -+{ -+ Q_D( const Annotation ); -+ -+ if (!d->pdfAnnot) -+ return d->contents; -+ -+ return UnicodeParsedString( d->pdfAnnot->getContents() ); -+} -+ -+void Annotation::setContents( const QString &contents ) -+{ -+ Q_D( Annotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->contents = contents; -+ return; -+ } -+ -+ GooString *s = QStringToUnicodeGooString(contents); -+ d->pdfAnnot->setContents(s); -+ delete s; -+} -+ -+QString Annotation::uniqueName() const -+{ -+ Q_D( const Annotation ); -+ -+ if (!d->pdfAnnot) -+ return d->uniqueName; -+ -+ return UnicodeParsedString( d->pdfAnnot->getName() ); -+} -+ -+void Annotation::setUniqueName( const QString &uniqueName ) -+{ -+ Q_D( Annotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->uniqueName = uniqueName; -+ return; -+ } -+ -+ QByteArray ascii = uniqueName.toAscii(); -+ GooString s(ascii.constData()); -+ d->pdfAnnot->setName(&s); -+} -+ -+QDateTime Annotation::modificationDate() const -+{ -+ Q_D( const Annotation ); -+ -+ if (!d->pdfAnnot) -+ return d->modDate; -+ -+ if ( d->pdfAnnot->getModified() ) -+ return convertDate( d->pdfAnnot->getModified()->c_str() ); -+ else -+ return QDateTime(); -+} -+ -+void Annotation::setModificationDate( const QDateTime &date ) -+{ -+ Q_D( Annotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->modDate = date; -+ return; -+ } -+ -+#if 0 // TODO: Conversion routine is broken -+ if (d->pdfAnnot) -+ { -+ time_t t = date.toTime_t(); -+ GooString *s = timeToDateString(&t); -+ d->pdfAnnot->setModified(s); -+ delete s; -+ } -+#endif -+} -+ -+QDateTime Annotation::creationDate() const -+{ -+ Q_D( const Annotation ); -+ -+ if (!d->pdfAnnot) -+ return d->creationDate; -+ -+ const AnnotMarkup *markupann = dynamic_cast(d->pdfAnnot); -+ -+ if (markupann && markupann->getDate()) -+ return convertDate( markupann->getDate()->c_str() ); -+ -+ return modificationDate(); -+} -+ -+void Annotation::setCreationDate( const QDateTime &date ) -+{ -+ Q_D( Annotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->creationDate = date; -+ return; -+ } -+ -+#if 0 // TODO: Conversion routine is broken -+ AnnotMarkup *markupann = dynamic_cast(d->pdfAnnot); -+ if (markupann) -+ { -+ time_t t = date.toTime_t(); -+ GooString *s = timeToDateString(&t); -+ markupann->setDate(s); -+ delete s; -+ } -+#endif -+} -+ -+static int fromPdfFlags(int flags) -+{ -+ int qtflags = 0; -+ -+ if ( flags & Annot::flagHidden ) -+ qtflags |= Annotation::Hidden; -+ if ( flags & Annot::flagNoZoom ) -+ qtflags |= Annotation::FixedSize; -+ if ( flags & Annot::flagNoRotate ) -+ qtflags |= Annotation::FixedRotation; -+ if ( !( flags & Annot::flagPrint ) ) -+ qtflags |= Annotation::DenyPrint; -+ if ( flags & Annot::flagReadOnly ) -+ qtflags |= (Annotation::DenyWrite | Annotation::DenyDelete); -+ if ( flags & Annot::flagLocked ) -+ qtflags |= Annotation::DenyDelete; -+ if ( flags & Annot::flagToggleNoView ) -+ qtflags |= Annotation::ToggleHidingOnMouse; -+ -+ return qtflags; -+} -+ -+static int toPdfFlags(int qtflags) -+{ -+ int flags = 0; -+ -+ if ( qtflags & Annotation::Hidden ) -+ flags |= Annot::flagHidden; -+ if ( qtflags & Annotation::FixedSize ) -+ flags |= Annot::flagNoZoom; -+ if ( qtflags & Annotation::FixedRotation ) -+ flags |= Annot::flagNoRotate; -+ if ( !( qtflags & Annotation::DenyPrint ) ) -+ flags |= Annot::flagPrint; -+ if ( qtflags & Annotation::DenyWrite ) -+ flags |= Annot::flagReadOnly; -+ if ( qtflags & Annotation::DenyDelete ) -+ flags |= Annot::flagLocked; -+ if ( qtflags & Annotation::ToggleHidingOnMouse ) -+ flags |= Annot::flagToggleNoView; -+ -+ return flags; -+} -+ -+int Annotation::flags() const -+{ -+ Q_D( const Annotation ); -+ -+ if (!d->pdfAnnot) -+ return d->flags; -+ -+ return fromPdfFlags( d->pdfAnnot->getFlags() ); -+} -+ -+void Annotation::setFlags( int flags ) -+{ -+ Q_D( Annotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->flags = flags; -+ return; -+ } -+ -+ d->pdfAnnot->setFlags(toPdfFlags( flags )); -+} -+ -+QRectF Annotation::boundary() const -+{ -+ Q_D( const Annotation ); -+ -+ if (!d->pdfAnnot) -+ return d->boundary; -+ -+ const PDFRectangle * rect = d->pdfAnnot->getRect(); -+ return d->fromPdfRectangle( *rect ); -+} -+ -+void Annotation::setBoundary( const QRectF &boundary ) -+{ -+ Q_D( Annotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->boundary = boundary; -+ return; -+ } -+ -+ PDFRectangle rect = d->boundaryToPdfRectangle( boundary, flags() ); -+ d->pdfAnnot->setRect(&rect); -+} -+ -+Annotation::Style Annotation::style() const -+{ -+ Q_D( const Annotation ); -+ -+ if (!d->pdfAnnot) -+ return d->style; -+ -+ Style s; -+ s.setColor(convertAnnotColor( d->pdfAnnot->getColor() )); -+ -+ const AnnotMarkup *markupann = dynamic_cast(d->pdfAnnot); -+ if (markupann) -+ s.setOpacity( markupann->getOpacity() ); -+ -+ const AnnotBorder *border = d->pdfAnnot->getBorder(); -+ if (border) -+ { -+ if ( border->getType() == AnnotBorder::typeArray ) -+ { -+ const AnnotBorderArray *border_array = static_cast(border); -+ s.setXCorners( border_array->getHorizontalCorner() ); -+ s.setYCorners( border_array->getVerticalCorner() ); -+ } -+ -+ s.setWidth( border->getWidth() ); -+ s.setLineStyle((Annotation::LineStyle)( 1 << border->getStyle() )); -+ -+ const int dashArrLen = border->getDashLength(); -+ const double* dashArrData = border->getDash(); -+ QVector dashArrVect( dashArrLen ); -+ for (int i = 0; i < dashArrLen; ++i) -+ dashArrVect[i] = dashArrData[i]; -+ s.setDashArray(dashArrVect); -+ } -+ -+ AnnotBorderEffect *border_effect; -+ switch (d->pdfAnnot->getType()) -+ { -+ case Annot::typeFreeText: -+ border_effect = static_cast(d->pdfAnnot)->getBorderEffect(); -+ break; -+ case Annot::typeSquare: -+ case Annot::typeCircle: -+ border_effect = static_cast(d->pdfAnnot)->getBorderEffect(); -+ break; -+ default: -+ border_effect = nullptr; -+ } -+ if (border_effect) -+ { -+ s.setLineEffect( (Annotation::LineEffect)border_effect->getEffectType() ); -+ s.setEffectIntensity( border_effect->getIntensity() ); -+ } -+ -+ return s; -+} -+ -+void Annotation::setStyle( const Annotation::Style& style ) -+{ -+ Q_D( Annotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->style = style; -+ return; -+ } -+ -+ d->pdfAnnot->setColor(convertQColor( style.color() )); -+ -+ AnnotMarkup *markupann = dynamic_cast(d->pdfAnnot); -+ if (markupann) -+ markupann->setOpacity( style.opacity() ); -+ -+ auto border = std::make_unique(); -+ border->setWidth( style.width() ); -+ border->setHorizontalCorner( style.xCorners() ); -+ border->setVerticalCorner( style.yCorners() ); -+ d->pdfAnnot->setBorder(std::move(border)); -+} -+ -+Annotation::Popup Annotation::popup() const -+{ -+ Q_D( const Annotation ); -+ -+ if (!d->pdfAnnot) -+ return d->popup; -+ -+ Popup w; -+ AnnotPopup *popup = nullptr; -+ int flags = -1; // Not initialized -+ -+ const AnnotMarkup *markupann = dynamic_cast(d->pdfAnnot); -+ if (markupann) -+ { -+ popup = markupann->getPopup(); -+ w.setSummary(UnicodeParsedString( markupann->getSubject() )); -+ } -+ -+ if (popup) -+ { -+ flags = fromPdfFlags( popup->getFlags() ) & ( Annotation::Hidden | -+ Annotation::FixedSize | Annotation::FixedRotation ); -+ -+ if (!popup->getOpen()) -+ flags |= Annotation::Hidden; -+ -+ const PDFRectangle * rect = popup->getRect(); -+ w.setGeometry( d->fromPdfRectangle( *rect ) ); -+ } -+ -+ if (d->pdfAnnot->getType() == Annot::typeText) -+ { -+ const AnnotText * textann = static_cast(d->pdfAnnot); -+ -+ // Text annotations default to same rect as annotation -+ if (flags == -1) -+ { -+ flags = 0; -+ w.setGeometry( boundary() ); -+ } -+ -+ // If text is not 'opened', force window hiding. if the window -+ // was parsed from popup, the flag should already be set -+ if ( !textann->getOpen() && flags != -1 ) -+ flags |= Annotation::Hidden; -+ } -+ -+ w.setFlags(flags); -+ -+ return w; -+} -+ -+void Annotation::setPopup( const Annotation::Popup& popup ) -+{ -+ Q_D( Annotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->popup = popup; -+ return; -+ } -+ -+#if 0 /* TODO: Remove old popup and add AnnotPopup to page */ -+ AnnotMarkup *markupann = dynamic_cast(d->pdfAnnot); -+ if (!markupann) -+ return; -+ -+ // Create a new AnnotPopup and assign it to pdfAnnot -+ PDFRectangle rect = d->toPdfRectangle( popup.geometry() ); -+ AnnotPopup * p = new AnnotPopup( d->pdfPage->getDoc(), &rect ); -+ p->setOpen( !(popup.flags() & Annotation::Hidden) ); -+ if (!popup.summary().isEmpty()) -+ { -+ GooString *s = QStringToUnicodeGooString(popup.summary()); -+ markupann->setLabel(s); -+ delete s; -+ } -+ markupann->setPopup(p); -+#endif -+} -+ -+Annotation::RevScope Annotation::revisionScope() const -+{ -+ Q_D( const Annotation ); -+ -+ if (!d->pdfAnnot) -+ return d->revisionScope; -+ -+ const AnnotMarkup *markupann = dynamic_cast(d->pdfAnnot); -+ -+ if (markupann && markupann->getInReplyToID() != 0) -+ { -+ switch (markupann->getReplyTo()) -+ { -+ case AnnotMarkup::replyTypeR: -+ return Annotation::Reply; -+ case AnnotMarkup::replyTypeGroup: -+ return Annotation::Group; -+ } -+ } -+ -+ return Annotation::Root; // It's not a revision -+} -+ -+Annotation::RevType Annotation::revisionType() const -+{ -+ Q_D( const Annotation ); -+ -+ if (!d->pdfAnnot) -+ return d->revisionType; -+ -+ const AnnotText *textann = dynamic_cast(d->pdfAnnot); -+ -+ if (textann && textann->getInReplyToID() != 0) -+ { -+ switch (textann->getState()) -+ { -+ case AnnotText::stateMarked: -+ return Annotation::Marked; -+ case AnnotText::stateUnmarked: -+ return Annotation::Unmarked; -+ case AnnotText::stateAccepted: -+ return Annotation::Accepted; -+ case AnnotText::stateRejected: -+ return Annotation::Rejected; -+ case AnnotText::stateCancelled: -+ return Annotation::Cancelled; -+ case AnnotText::stateCompleted: -+ return Annotation::Completed; -+ default: -+ break; -+ } -+ } -+ -+ return Annotation::None; -+} -+ -+QList Annotation::revisions() const -+{ -+ Q_D( const Annotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ /* Return aliases, whose ownership goes to the caller */ -+ QList res; -+ foreach (Annotation *rev, d->revisions) -+ res.append( rev->d_ptr->makeAlias() ); -+ return res; -+ } -+ -+ /* If the annotation doesn't live in a object on its own (eg bug51361), it -+ * has no ref, therefore it can't have revisions */ -+ if ( !d->pdfAnnot->getHasRef() ) -+ return QList(); -+ -+ return AnnotationPrivate::findAnnotations( d->pdfPage, d->parentDoc, QSet(), d->pdfAnnot->getId() ); -+} -+ -+//END Annotation implementation -+ -+ -+/** TextAnnotation [Annotation] */ -+class TextAnnotationPrivate : public AnnotationPrivate -+{ -+ public: -+ TextAnnotationPrivate(); -+ Annotation * makeAlias(); -+ Annot* createNativeAnnot(::Page *destPage, DocumentData *doc); -+ void setDefaultAppearanceToNative(); -+ std::unique_ptr getDefaultAppearanceFromNative() const; -+ -+ // data fields -+ TextAnnotation::TextType textType; -+ QString textIcon; -+ QFont textFont; -+ QColor textColor; -+ int inplaceAlign; // 0:left, 1:center, 2:right -+ QVector inplaceCallout; -+ TextAnnotation::InplaceIntent inplaceIntent; -+}; -+ -+TextAnnotationPrivate::TextAnnotationPrivate() -+ : AnnotationPrivate(), textType( TextAnnotation::Linked ), -+ textIcon( "Note" ), inplaceAlign( 0 ), -+ inplaceIntent( TextAnnotation::Unknown ) -+{ -+} -+ -+Annotation * TextAnnotationPrivate::makeAlias() -+{ -+ return new TextAnnotation(*this); -+} -+ -+Annot* TextAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc) -+{ -+ // Setters are defined in the public class -+ TextAnnotation *q = static_cast( makeAlias() ); -+ -+ // Set page and contents -+ pdfPage = destPage; -+ parentDoc = doc; -+ -+ // Set pdfAnnot -+ PDFRectangle rect = boundaryToPdfRectangle(boundary, flags); -+ if (textType == TextAnnotation::Linked) { -+ pdfAnnot = new AnnotText(destPage->getDoc(), &rect); -+ } else { -+ DefaultAppearance da{ { objName, "Invalid_font" }, static_cast( textFont.pointSize() ), std::unique_ptr{ convertQColor( textColor ) } }; -+ pdfAnnot = new AnnotFreeText(destPage->getDoc(), &rect, da); -+ } -+ -+ // Set properties -+ flushBaseAnnotationProperties(); -+ q->setTextIcon(textIcon); -+ q->setInplaceAlign(inplaceAlign); -+ q->setCalloutPoints(inplaceCallout); -+ q->setInplaceIntent(inplaceIntent); -+ -+ delete q; -+ -+ inplaceCallout.clear(); // Free up memory -+ -+ return pdfAnnot; -+} -+ -+void TextAnnotationPrivate::setDefaultAppearanceToNative() -+{ -+ if (pdfAnnot && pdfAnnot->getType() == Annot::typeFreeText) { -+ AnnotFreeText * ftextann = static_cast(pdfAnnot); -+ DefaultAppearance da{ { objName, "Invalid_font" }, static_cast( textFont.pointSize() ), std::unique_ptr{ convertQColor( textColor ) } }; -+ ftextann->setDefaultAppearance( da ); -+ } -+} -+ -+std::unique_ptr TextAnnotationPrivate::getDefaultAppearanceFromNative() const -+{ -+ if (pdfAnnot && pdfAnnot->getType() == Annot::typeFreeText) { -+ AnnotFreeText * ftextann = static_cast(pdfAnnot); -+ return ftextann->getDefaultAppearance(); -+ } else { -+ return nullptr; -+ } -+} -+ -+TextAnnotation::TextAnnotation( TextAnnotation::TextType type ) -+ : Annotation( *new TextAnnotationPrivate() ) -+{ -+ setTextType( type ); -+} -+ -+TextAnnotation::TextAnnotation(TextAnnotationPrivate &dd) -+ : Annotation( dd ) -+{} -+ -+TextAnnotation::TextAnnotation( const QDomNode & node ) -+ : Annotation( *new TextAnnotationPrivate, node ) -+{ -+ // loop through the whole children looking for a 'text' element -+ QDomNode subNode = node.firstChild(); -+ while( subNode.isElement() ) -+ { -+ QDomElement e = subNode.toElement(); -+ subNode = subNode.nextSibling(); -+ if ( e.tagName() != "text" ) -+ continue; -+ -+ // parse the attributes -+ if ( e.hasAttribute( "type" ) ) -+ setTextType((TextAnnotation::TextType)e.attribute( "type" ).toInt()); -+ if ( e.hasAttribute( "icon" ) ) -+ setTextIcon(e.attribute( "icon" )); -+ if ( e.hasAttribute( "font" ) ) -+ { -+ QFont font; -+ font.fromString( e.attribute( "font" ) ); -+ setTextFont(font); -+ if ( e.hasAttribute( "fontColor" ) ) -+ { -+ const QColor color = QColor(e.attribute( "fontColor" ) ); -+ setTextColor(color); -+ } -+ } -+ if ( e.hasAttribute( "align" ) ) -+ setInplaceAlign(e.attribute( "align" ).toInt()); -+ if ( e.hasAttribute( "intent" ) ) -+ setInplaceIntent((TextAnnotation::InplaceIntent)e.attribute( "intent" ).toInt()); -+ -+ // parse the subnodes -+ QDomNode eSubNode = e.firstChild(); -+ while ( eSubNode.isElement() ) -+ { -+ QDomElement ee = eSubNode.toElement(); -+ eSubNode = eSubNode.nextSibling(); -+ -+ if ( ee.tagName() == "escapedText" ) -+ { -+ setInplaceText(ee.firstChild().toCDATASection().data()); -+ } -+ else if ( ee.tagName() == "callout" ) -+ { -+ QVector points(3); -+ points[0] = QPointF(ee.attribute( "ax" ).toDouble(), -+ ee.attribute( "ay" ).toDouble()); -+ points[1] = QPointF(ee.attribute( "bx" ).toDouble(), -+ ee.attribute( "by" ).toDouble()); -+ points[2] = QPointF(ee.attribute( "cx" ).toDouble(), -+ ee.attribute( "cy" ).toDouble()); -+ setCalloutPoints(points); -+ } -+ } -+ -+ // loading complete -+ break; -+ } -+} -+ -+TextAnnotation::~TextAnnotation() -+{ -+} -+ -+void TextAnnotation::store( QDomNode & node, QDomDocument & document ) const -+{ -+ // store base annotation properties -+ storeBaseAnnotationProperties( node, document ); -+ -+ // create [text] element -+ QDomElement textElement = document.createElement( "text" ); -+ node.appendChild( textElement ); -+ -+ // store the optional attributes -+ if ( textType() != Linked ) -+ textElement.setAttribute( "type", (int)textType() ); -+ if ( textIcon() != "Note" ) -+ textElement.setAttribute( "icon", textIcon() ); -+ if ( inplaceAlign() ) -+ textElement.setAttribute( "align", inplaceAlign() ); -+ if ( inplaceIntent() != Unknown ) -+ textElement.setAttribute( "intent", (int)inplaceIntent() ); -+ -+ textElement.setAttribute( "font", textFont().toString() ); -+ textElement.setAttribute( "fontColor", textColor().name() ); -+ -+ // Sub-Node-1 - escapedText -+ if ( !inplaceText().isEmpty() ) -+ { -+ QDomElement escapedText = document.createElement( "escapedText" ); -+ textElement.appendChild( escapedText ); -+ QDomCDATASection textCData = document.createCDATASection( inplaceText() ); -+ escapedText.appendChild( textCData ); -+ } -+ -+ // Sub-Node-2 - callout -+ if ( calloutPoint(0).x() != 0.0 ) -+ { -+ QDomElement calloutElement = document.createElement( "callout" ); -+ textElement.appendChild( calloutElement ); -+ calloutElement.setAttribute( "ax", QString::number( calloutPoint(0).x() ) ); -+ calloutElement.setAttribute( "ay", QString::number( calloutPoint(0).y() ) ); -+ calloutElement.setAttribute( "bx", QString::number( calloutPoint(1).x() ) ); -+ calloutElement.setAttribute( "by", QString::number( calloutPoint(1).y() ) ); -+ calloutElement.setAttribute( "cx", QString::number( calloutPoint(2).x() ) ); -+ calloutElement.setAttribute( "cy", QString::number( calloutPoint(2).y() ) ); -+ } -+} -+ -+Annotation::SubType TextAnnotation::subType() const -+{ -+ return AText; -+} -+ -+TextAnnotation::TextType TextAnnotation::textType() const -+{ -+ Q_D( const TextAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->textType; -+ -+ return d->pdfAnnot->getType() == Annot::typeText ? -+ TextAnnotation::Linked : TextAnnotation::InPlace; -+} -+ -+void TextAnnotation::setTextType( TextAnnotation::TextType type ) -+{ -+ Q_D( TextAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->textType = type; -+ return; -+ } -+ -+ // Type cannot be changed if annotation is already tied -+} -+ -+QString TextAnnotation::textIcon() const -+{ -+ Q_D( const TextAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->textIcon; -+ -+ if (d->pdfAnnot->getType() == Annot::typeText) -+ { -+ const AnnotText * textann = static_cast(d->pdfAnnot); -+ return QString::fromLatin1( textann->getIcon()->c_str() ); -+ } -+ -+ return QString(); -+} -+ -+void TextAnnotation::setTextIcon( const QString &icon ) -+{ -+ Q_D( TextAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->textIcon = icon; -+ return; -+ } -+ -+ if (d->pdfAnnot->getType() == Annot::typeText) -+ { -+ AnnotText * textann = static_cast(d->pdfAnnot); -+ QByteArray encoded = icon.toLatin1(); -+ GooString s(encoded.constData()); -+ textann->setIcon(&s); -+ } -+} -+ -+QFont TextAnnotation::textFont() const -+{ -+ Q_D( const TextAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->textFont; -+ -+ QFont font; -+ -+ if (d->pdfAnnot->getType() == Annot::typeFreeText) -+ { -+ if ( std::unique_ptr da{ d->getDefaultAppearanceFromNative() } ) -+ { -+ font.setPointSize( da->getFontPtSize() ); -+ } -+ } -+ -+ return font; -+} -+ -+void TextAnnotation::setTextFont( const QFont &font ) -+{ -+ Q_D( TextAnnotation ); -+ d->textFont = font; -+ d->textColor = Qt::black; -+ -+ d->setDefaultAppearanceToNative(); -+} -+ -+QColor TextAnnotation::textColor() const -+{ -+ Q_D( const TextAnnotation ); -+ -+ if ( !d->pdfAnnot ) -+ return d->textColor; -+ -+ if ( std::unique_ptr da{ d->getDefaultAppearanceFromNative() } ) -+ { -+ return convertAnnotColor( da->getFontColor() ); -+ } -+ -+ return {}; -+} -+ -+void TextAnnotation::setTextColor( const QColor &color ) -+{ -+ Q_D( TextAnnotation ); -+ d->textColor = color; -+ -+ d->setDefaultAppearanceToNative(); -+} -+ -+int TextAnnotation::inplaceAlign() const -+{ -+ Q_D( const TextAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->inplaceAlign; -+ -+ if (d->pdfAnnot->getType() == Annot::typeFreeText) -+ { -+ const AnnotFreeText * ftextann = static_cast(d->pdfAnnot); -+ return ftextann->getQuadding(); -+ } -+ -+ return 0; -+} -+ -+void TextAnnotation::setInplaceAlign( int align ) -+{ -+ Q_D( TextAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->inplaceAlign = align; -+ return; -+ } -+ -+ if (d->pdfAnnot->getType() == Annot::typeFreeText) -+ { -+ AnnotFreeText * ftextann = static_cast(d->pdfAnnot); -+ ftextann->setQuadding((AnnotFreeText::AnnotFreeTextQuadding)align); -+ } -+} -+ -+QString TextAnnotation::inplaceText() const -+{ -+ return contents(); -+} -+ -+void TextAnnotation::setInplaceText( const QString &text ) -+{ -+ setContents(text); -+} -+ -+QPointF TextAnnotation::calloutPoint( int id ) const -+{ -+ const QVector points = calloutPoints(); -+ if ( id < 0 || id >= points.size() ) -+ return QPointF(); -+ else -+ return points[id]; -+} -+ -+QVector TextAnnotation::calloutPoints() const -+{ -+ Q_D( const TextAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->inplaceCallout; -+ -+ if (d->pdfAnnot->getType() == Annot::typeText) -+ return QVector(); -+ -+ const AnnotFreeText * ftextann = static_cast(d->pdfAnnot); -+ const AnnotCalloutLine *callout = ftextann->getCalloutLine(); -+ -+ if (!callout) -+ return QVector(); -+ -+ double MTX[6]; -+ d->fillTransformationMTX(MTX); -+ -+ const AnnotCalloutMultiLine * callout_v6 = dynamic_cast(callout); -+ QVector res(callout_v6 ? 3 : 2); -+ XPDFReader::transform(MTX, callout->getX1(), callout->getY1(), res[0]); -+ XPDFReader::transform(MTX, callout->getX2(), callout->getY2(), res[1]); -+ if (callout_v6) -+ XPDFReader::transform(MTX, callout_v6->getX3(), callout_v6->getY3(), res[2]); -+ return res; -+} -+ -+void TextAnnotation::setCalloutPoints( const QVector &points ) -+{ -+ Q_D( TextAnnotation ); -+ if (!d->pdfAnnot) -+ { -+ d->inplaceCallout = points; -+ return; -+ } -+ -+ if (d->pdfAnnot->getType() != Annot::typeFreeText) -+ return; -+ -+ AnnotFreeText * ftextann = static_cast(d->pdfAnnot); -+ const int count = points.size(); -+ -+ if (count == 0) -+ { -+ ftextann->setCalloutLine(0); -+ return; -+ } -+ -+ if (count != 2 && count != 3) -+ { -+ error(errSyntaxError, -1, "Expected zero, two or three points for callout"); -+ return; -+ } -+ -+ AnnotCalloutLine *callout; -+ double x1, y1, x2, y2; -+ double MTX[6]; -+ d->fillTransformationMTX(MTX); -+ -+ XPDFReader::invTransform( MTX, points[0], x1, y1 ); -+ XPDFReader::invTransform( MTX, points[1], x2, y2 ); -+ if (count == 3) -+ { -+ double x3, y3; -+ XPDFReader::invTransform( MTX, points[2], x3, y3 ); -+ callout = new AnnotCalloutMultiLine(x1, y1, x2, y2, x3, y3); -+ } -+ else -+ { -+ callout = new AnnotCalloutLine(x1, y1, x2, y2); -+ } -+ -+ ftextann->setCalloutLine(callout); -+ delete callout; -+} -+ -+TextAnnotation::InplaceIntent TextAnnotation::inplaceIntent() const -+{ -+ Q_D( const TextAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->inplaceIntent; -+ -+ if (d->pdfAnnot->getType() == Annot::typeFreeText) -+ { -+ const AnnotFreeText * ftextann = static_cast(d->pdfAnnot); -+ return (TextAnnotation::InplaceIntent)ftextann->getIntent(); -+ } -+ -+ return TextAnnotation::Unknown; -+} -+ -+void TextAnnotation::setInplaceIntent( TextAnnotation::InplaceIntent intent ) -+{ -+ Q_D( TextAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->inplaceIntent = intent; -+ return; -+ } -+ -+ if (d->pdfAnnot->getType() == Annot::typeFreeText) -+ { -+ AnnotFreeText * ftextann = static_cast(d->pdfAnnot); -+ ftextann->setIntent((AnnotFreeText::AnnotFreeTextIntent)intent); -+ } -+} -+ -+ -+/** LineAnnotation [Annotation] */ -+class LineAnnotationPrivate : public AnnotationPrivate -+{ -+ public: -+ LineAnnotationPrivate(); -+ Annotation * makeAlias(); -+ Annot* createNativeAnnot(::Page *destPage, DocumentData *doc); -+ -+ // data fields (note uses border for rendering style) -+ QLinkedList linePoints; -+ LineAnnotation::TermStyle lineStartStyle; -+ LineAnnotation::TermStyle lineEndStyle; -+ bool lineClosed : 1; // (if true draw close shape) -+ bool lineShowCaption : 1; -+ LineAnnotation::LineType lineType; -+ QColor lineInnerColor; -+ double lineLeadingFwdPt; -+ double lineLeadingBackPt; -+ LineAnnotation::LineIntent lineIntent; -+}; -+ -+LineAnnotationPrivate::LineAnnotationPrivate() -+ : AnnotationPrivate(), lineStartStyle( LineAnnotation::None ), -+ lineEndStyle( LineAnnotation::None ), lineClosed( false ), -+ lineShowCaption( false ), lineLeadingFwdPt( 0 ), -+ lineLeadingBackPt( 0 ), lineIntent( LineAnnotation::Unknown ) -+{ -+} -+ -+Annotation * LineAnnotationPrivate::makeAlias() -+{ -+ return new LineAnnotation(*this); -+} -+ -+Annot* LineAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc) -+{ -+ // Setters are defined in the public class -+ LineAnnotation *q = static_cast( makeAlias() ); -+ -+ // Set page and document -+ pdfPage = destPage; -+ parentDoc = doc; -+ -+ // Set pdfAnnot -+ PDFRectangle rect = boundaryToPdfRectangle(boundary, flags); -+ if (lineType == LineAnnotation::StraightLine) -+ { -+ pdfAnnot = new AnnotLine(doc->doc, &rect); -+ } -+ else -+ { -+ pdfAnnot = new AnnotPolygon(doc->doc, &rect, -+ lineClosed ? Annot::typePolygon : Annot::typePolyLine ); -+ } -+ -+ // Set properties -+ flushBaseAnnotationProperties(); -+ q->setLinePoints(linePoints); -+ q->setLineStartStyle(lineStartStyle); -+ q->setLineEndStyle(lineEndStyle); -+ q->setLineInnerColor(lineInnerColor); -+ q->setLineLeadingForwardPoint(lineLeadingFwdPt); -+ q->setLineLeadingBackPoint(lineLeadingBackPt); -+ q->setLineShowCaption(lineShowCaption); -+ q->setLineIntent(lineIntent); -+ -+ delete q; -+ -+ linePoints.clear(); // Free up memory -+ -+ return pdfAnnot; -+} -+ -+LineAnnotation::LineAnnotation( LineAnnotation::LineType type ) -+ : Annotation( *new LineAnnotationPrivate() ) -+{ -+ setLineType(type); -+} -+ -+LineAnnotation::LineAnnotation(LineAnnotationPrivate &dd) -+ : Annotation( dd ) -+{} -+ -+LineAnnotation::LineAnnotation( const QDomNode & node ) -+ : Annotation( *new LineAnnotationPrivate(), node ) -+{ -+ // loop through the whole children looking for a 'line' element -+ QDomNode subNode = node.firstChild(); -+ while( subNode.isElement() ) -+ { -+ QDomElement e = subNode.toElement(); -+ subNode = subNode.nextSibling(); -+ if ( e.tagName() != "line" ) -+ continue; -+ -+ // parse the attributes -+ if ( e.hasAttribute( "startStyle" ) ) -+ setLineStartStyle((LineAnnotation::TermStyle)e.attribute( "startStyle" ).toInt()); -+ if ( e.hasAttribute( "endStyle" ) ) -+ setLineEndStyle((LineAnnotation::TermStyle)e.attribute( "endStyle" ).toInt()); -+ if ( e.hasAttribute( "closed" ) ) -+ setLineClosed(e.attribute( "closed" ).toInt()); -+ if ( e.hasAttribute( "innerColor" ) ) -+ setLineInnerColor(QColor( e.attribute( "innerColor" ) )); -+ if ( e.hasAttribute( "leadFwd" ) ) -+ setLineLeadingForwardPoint(e.attribute( "leadFwd" ).toDouble()); -+ if ( e.hasAttribute( "leadBack" ) ) -+ setLineLeadingBackPoint(e.attribute( "leadBack" ).toDouble()); -+ if ( e.hasAttribute( "showCaption" ) ) -+ setLineShowCaption(e.attribute( "showCaption" ).toInt()); -+ if ( e.hasAttribute( "intent" ) ) -+ setLineIntent((LineAnnotation::LineIntent)e.attribute( "intent" ).toInt()); -+ -+ // parse all 'point' subnodes -+ QLinkedList points; -+ QDomNode pointNode = e.firstChild(); -+ while ( pointNode.isElement() ) -+ { -+ QDomElement pe = pointNode.toElement(); -+ pointNode = pointNode.nextSibling(); -+ -+ if ( pe.tagName() != "point" ) -+ continue; -+ -+ QPointF p(pe.attribute( "x", "0.0" ).toDouble(), pe.attribute( "y", "0.0" ).toDouble()); -+ points.append( p ); -+ } -+ setLinePoints(points); -+ setLineType(points.size() == 2 ? StraightLine : Polyline); -+ -+ // loading complete -+ break; -+ } -+} -+ -+LineAnnotation::~LineAnnotation() -+{ -+} -+ -+void LineAnnotation::store( QDomNode & node, QDomDocument & document ) const -+{ -+ // store base annotation properties -+ storeBaseAnnotationProperties( node, document ); -+ -+ // create [line] element -+ QDomElement lineElement = document.createElement( "line" ); -+ node.appendChild( lineElement ); -+ -+ // store the attributes -+ if ( lineStartStyle() != None ) -+ lineElement.setAttribute( "startStyle", (int)lineStartStyle() ); -+ if ( lineEndStyle() != None ) -+ lineElement.setAttribute( "endStyle", (int)lineEndStyle() ); -+ if ( isLineClosed() ) -+ lineElement.setAttribute( "closed", isLineClosed() ); -+ if ( lineInnerColor().isValid() ) -+ lineElement.setAttribute( "innerColor", lineInnerColor().name() ); -+ if ( lineLeadingForwardPoint() != 0.0 ) -+ lineElement.setAttribute( "leadFwd", QString::number( lineLeadingForwardPoint() ) ); -+ if ( lineLeadingBackPoint() != 0.0 ) -+ lineElement.setAttribute( "leadBack", QString::number( lineLeadingBackPoint() ) ); -+ if ( lineShowCaption() ) -+ lineElement.setAttribute( "showCaption", lineShowCaption() ); -+ if ( lineIntent() != Unknown ) -+ lineElement.setAttribute( "intent", lineIntent() ); -+ -+ // append the list of points -+ const QLinkedList points = linePoints(); -+ if ( points.count() > 1 ) -+ { -+ QLinkedList::const_iterator it = points.begin(), end = points.end(); -+ while ( it != end ) -+ { -+ const QPointF & p = *it; -+ QDomElement pElement = document.createElement( "point" ); -+ lineElement.appendChild( pElement ); -+ pElement.setAttribute( "x", QString::number( p.x() ) ); -+ pElement.setAttribute( "y", QString::number( p.y() ) ); -+ ++it; -+ } -+ } -+} -+ -+Annotation::SubType LineAnnotation::subType() const -+{ -+ return ALine; -+} -+ -+LineAnnotation::LineType LineAnnotation::lineType() const -+{ -+ Q_D( const LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->lineType; -+ -+ return (d->pdfAnnot->getType() == Annot::typeLine) ? -+ LineAnnotation::StraightLine : LineAnnotation::Polyline; -+} -+ -+void LineAnnotation::setLineType( LineAnnotation::LineType type ) -+{ -+ Q_D( LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->lineType = type; -+ return; -+ } -+ -+ // Type cannot be changed if annotation is already tied -+} -+ -+QLinkedList LineAnnotation::linePoints() const -+{ -+ Q_D( const LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->linePoints; -+ -+ double MTX[6]; -+ d->fillTransformationMTX(MTX); -+ -+ QLinkedList res; -+ if (d->pdfAnnot->getType() == Annot::typeLine) -+ { -+ const AnnotLine * lineann = static_cast(d->pdfAnnot); -+ QPointF p; -+ XPDFReader::transform(MTX, lineann->getX1(), lineann->getY1(), p); -+ res.append(p); -+ XPDFReader::transform(MTX, lineann->getX2(), lineann->getY2(), p); -+ res.append(p); -+ } -+ else -+ { -+ const AnnotPolygon * polyann = static_cast(d->pdfAnnot); -+ const AnnotPath * vertices = polyann->getVertices(); -+ -+ for (int i = 0; i < vertices->getCoordsLength(); ++i) -+ { -+ QPointF p; -+ XPDFReader::transform(MTX, vertices->getX(i), vertices->getY(i), p); -+ res.append(p); -+ } -+ } -+ -+ return res; -+} -+ -+void LineAnnotation::setLinePoints( const QLinkedList &points ) -+{ -+ Q_D( LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->linePoints = points; -+ return; -+ } -+ -+ if (d->pdfAnnot->getType() == Annot::typeLine) -+ { -+ AnnotLine *lineann = static_cast(d->pdfAnnot); -+ if (points.size() != 2) -+ { -+ error(errSyntaxError, -1, "Expected two points for a straight line"); -+ return; -+ } -+ double x1, y1, x2, y2; -+ double MTX[6]; -+ d->fillTransformationMTX(MTX); -+ XPDFReader::invTransform( MTX, points.first(), x1, y1 ); -+ XPDFReader::invTransform( MTX, points.last(), x2, y2 ); -+ lineann->setVertices(x1, y1, x2, y2); -+ } -+ else -+ { -+ AnnotPolygon *polyann = static_cast(d->pdfAnnot); -+ AnnotPath * p = d->toAnnotPath(points); -+ polyann->setVertices(p); -+ delete p; -+ } -+} -+ -+LineAnnotation::TermStyle LineAnnotation::lineStartStyle() const -+{ -+ Q_D( const LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->lineStartStyle; -+ -+ if (d->pdfAnnot->getType() == Annot::typeLine) -+ { -+ const AnnotLine * lineann = static_cast(d->pdfAnnot); -+ return (LineAnnotation::TermStyle)lineann->getStartStyle(); -+ } -+ else -+ { -+ const AnnotPolygon * polyann = static_cast(d->pdfAnnot); -+ return (LineAnnotation::TermStyle)polyann->getStartStyle(); -+ } -+} -+ -+void LineAnnotation::setLineStartStyle( LineAnnotation::TermStyle style ) -+{ -+ Q_D( LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->lineStartStyle = style; -+ return; -+ } -+ -+ if (d->pdfAnnot->getType() == Annot::typeLine) -+ { -+ AnnotLine *lineann = static_cast(d->pdfAnnot); -+ lineann->setStartEndStyle((AnnotLineEndingStyle)style, lineann->getEndStyle()); -+ } -+ else -+ { -+ AnnotPolygon *polyann = static_cast(d->pdfAnnot); -+ polyann->setStartEndStyle((AnnotLineEndingStyle)style, polyann->getEndStyle()); -+ } -+} -+ -+LineAnnotation::TermStyle LineAnnotation::lineEndStyle() const -+{ -+ Q_D( const LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->lineEndStyle; -+ -+ if (d->pdfAnnot->getType() == Annot::typeLine) -+ { -+ const AnnotLine * lineann = static_cast(d->pdfAnnot); -+ return (LineAnnotation::TermStyle)lineann->getEndStyle(); -+ } -+ else -+ { -+ const AnnotPolygon * polyann = static_cast(d->pdfAnnot); -+ return (LineAnnotation::TermStyle)polyann->getEndStyle(); -+ } -+} -+ -+void LineAnnotation::setLineEndStyle( LineAnnotation::TermStyle style ) -+{ -+ Q_D( LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->lineEndStyle = style; -+ return; -+ } -+ -+ if (d->pdfAnnot->getType() == Annot::typeLine) -+ { -+ AnnotLine *lineann = static_cast(d->pdfAnnot); -+ lineann->setStartEndStyle(lineann->getStartStyle(), (AnnotLineEndingStyle)style); -+ } -+ else -+ { -+ AnnotPolygon *polyann = static_cast(d->pdfAnnot); -+ polyann->setStartEndStyle(polyann->getStartStyle(), (AnnotLineEndingStyle)style); -+ } -+} -+ -+bool LineAnnotation::isLineClosed() const -+{ -+ Q_D( const LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->lineClosed; -+ -+ return d->pdfAnnot->getType() == Annot::typePolygon; -+} -+ -+void LineAnnotation::setLineClosed( bool closed ) -+{ -+ Q_D( LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->lineClosed = closed; -+ return; -+ } -+ -+ if (d->pdfAnnot->getType() != Annot::typeLine) -+ { -+ AnnotPolygon *polyann = static_cast(d->pdfAnnot); -+ -+ // Set new subtype and switch intent if necessary -+ if (closed) -+ { -+ polyann->setType(Annot::typePolygon); -+ if (polyann->getIntent() == AnnotPolygon::polylineDimension) -+ polyann->setIntent( AnnotPolygon::polygonDimension ); -+ } -+ else -+ { -+ polyann->setType(Annot::typePolyLine); -+ if (polyann->getIntent() == AnnotPolygon::polygonDimension) -+ polyann->setIntent( AnnotPolygon::polylineDimension ); -+ } -+ } -+} -+ -+QColor LineAnnotation::lineInnerColor() const -+{ -+ Q_D( const LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->lineInnerColor; -+ -+ AnnotColor * c; -+ -+ if (d->pdfAnnot->getType() == Annot::typeLine) -+ { -+ const AnnotLine * lineann = static_cast(d->pdfAnnot); -+ c = lineann->getInteriorColor(); -+ } -+ else -+ { -+ const AnnotPolygon * polyann = static_cast(d->pdfAnnot); -+ c = polyann->getInteriorColor(); -+ } -+ -+ return convertAnnotColor(c); -+} -+ -+void LineAnnotation::setLineInnerColor( const QColor &color ) -+{ -+ Q_D( LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->lineInnerColor = color; -+ return; -+ } -+ -+ auto c = convertQColor(color); -+ -+ if (d->pdfAnnot->getType() == Annot::typeLine) -+ { -+ AnnotLine *lineann = static_cast(d->pdfAnnot); -+ lineann->setInteriorColor(std::move(c)); -+ } -+ else -+ { -+ AnnotPolygon *polyann = static_cast(d->pdfAnnot); -+ polyann->setInteriorColor(std::move(c)); -+ } -+} -+ -+double LineAnnotation::lineLeadingForwardPoint() const -+{ -+ Q_D( const LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->lineLeadingFwdPt; -+ -+ if (d->pdfAnnot->getType() == Annot::typeLine) -+ { -+ const AnnotLine * lineann = static_cast(d->pdfAnnot); -+ return lineann->getLeaderLineLength(); -+ } -+ -+ return 0; -+} -+ -+void LineAnnotation::setLineLeadingForwardPoint( double point ) -+{ -+ Q_D( LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->lineLeadingFwdPt = point; -+ return; -+ } -+ -+ if (d->pdfAnnot->getType() == Annot::typeLine) -+ { -+ AnnotLine *lineann = static_cast(d->pdfAnnot); -+ lineann->setLeaderLineLength(point); -+ } -+} -+ -+double LineAnnotation::lineLeadingBackPoint() const -+{ -+ Q_D( const LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->lineLeadingBackPt; -+ -+ if (d->pdfAnnot->getType() == Annot::typeLine) -+ { -+ const AnnotLine * lineann = static_cast(d->pdfAnnot); -+ return lineann->getLeaderLineExtension(); -+ } -+ -+ return 0; -+} -+ -+void LineAnnotation::setLineLeadingBackPoint( double point ) -+{ -+ Q_D( LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->lineLeadingBackPt = point; -+ return; -+ } -+ -+ if (d->pdfAnnot->getType() == Annot::typeLine) -+ { -+ AnnotLine *lineann = static_cast(d->pdfAnnot); -+ lineann->setLeaderLineExtension(point); -+ } -+} -+ -+bool LineAnnotation::lineShowCaption() const -+{ -+ Q_D( const LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->lineShowCaption; -+ -+ if (d->pdfAnnot->getType() == Annot::typeLine) -+ { -+ const AnnotLine * lineann = static_cast(d->pdfAnnot); -+ return lineann->getCaption(); -+ } -+ -+ return false; -+} -+ -+void LineAnnotation::setLineShowCaption( bool show ) -+{ -+ Q_D( LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->lineShowCaption = show; -+ return; -+ } -+ -+ if (d->pdfAnnot->getType() == Annot::typeLine) -+ { -+ AnnotLine *lineann = static_cast(d->pdfAnnot); -+ lineann->setCaption(show); -+ } -+} -+ -+LineAnnotation::LineIntent LineAnnotation::lineIntent() const -+{ -+ Q_D( const LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->lineIntent; -+ -+ if (d->pdfAnnot->getType() == Annot::typeLine) -+ { -+ const AnnotLine * lineann = static_cast(d->pdfAnnot); -+ return (LineAnnotation::LineIntent)( lineann->getIntent() + 1 ); -+ } -+ else -+ { -+ const AnnotPolygon * polyann = static_cast(d->pdfAnnot); -+ if ( polyann->getIntent() == AnnotPolygon::polygonCloud ) -+ return LineAnnotation::PolygonCloud; -+ else // AnnotPolygon::polylineDimension, AnnotPolygon::polygonDimension -+ return LineAnnotation::Dimension; -+ } -+} -+ -+void LineAnnotation::setLineIntent( LineAnnotation::LineIntent intent ) -+{ -+ Q_D( LineAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->lineIntent = intent; -+ return; -+ } -+ -+ if ( intent == LineAnnotation::Unknown ) -+ return; // Do not set (actually, it should clear the property) -+ -+ if (d->pdfAnnot->getType() == Annot::typeLine) -+ { -+ AnnotLine * lineann = static_cast(d->pdfAnnot); -+ lineann->setIntent((AnnotLine::AnnotLineIntent)( intent - 1 )); -+ } -+ else -+ { -+ AnnotPolygon * polyann = static_cast(d->pdfAnnot); -+ if ( intent == LineAnnotation::PolygonCloud) -+ polyann->setIntent( AnnotPolygon::polygonCloud ); -+ else // LineAnnotation::Dimension -+ { -+ if ( d->pdfAnnot->getType() == Annot::typePolygon ) -+ polyann->setIntent( AnnotPolygon::polygonDimension ); -+ else // Annot::typePolyLine -+ polyann->setIntent( AnnotPolygon::polylineDimension ); -+ } -+ } -+} -+ -+ -+/** GeomAnnotation [Annotation] */ -+class GeomAnnotationPrivate : public AnnotationPrivate -+{ -+ public: -+ GeomAnnotationPrivate(); -+ Annotation * makeAlias(); -+ Annot* createNativeAnnot(::Page *destPage, DocumentData *doc); -+ -+ // data fields (note uses border for rendering style) -+ GeomAnnotation::GeomType geomType; -+ QColor geomInnerColor; -+}; -+ -+GeomAnnotationPrivate::GeomAnnotationPrivate() -+ : AnnotationPrivate(), geomType( GeomAnnotation::InscribedSquare ) -+{ -+} -+ -+Annotation * GeomAnnotationPrivate::makeAlias() -+{ -+ return new GeomAnnotation(*this); -+} -+ -+Annot* GeomAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc) -+{ -+ // Setters are defined in the public class -+ GeomAnnotation *q = static_cast( makeAlias() ); -+ -+ // Set page and document -+ pdfPage = destPage; -+ parentDoc = doc; -+ -+ Annot::AnnotSubtype type; -+ if (geomType == GeomAnnotation::InscribedSquare) -+ type = Annot::typeSquare; -+ else // GeomAnnotation::InscribedCircle -+ type = Annot::typeCircle; -+ -+ // Set pdfAnnot -+ PDFRectangle rect = boundaryToPdfRectangle(boundary, flags); -+ pdfAnnot = new AnnotGeometry(destPage->getDoc(), &rect, type); -+ -+ // Set properties -+ flushBaseAnnotationProperties(); -+ q->setGeomInnerColor(geomInnerColor); -+ -+ delete q; -+ return pdfAnnot; -+} -+ -+GeomAnnotation::GeomAnnotation() -+ : Annotation( *new GeomAnnotationPrivate() ) -+{} -+ -+GeomAnnotation::GeomAnnotation(GeomAnnotationPrivate &dd) -+ : Annotation( dd ) -+{} -+ -+GeomAnnotation::GeomAnnotation( const QDomNode & node ) -+ : Annotation( *new GeomAnnotationPrivate(), node ) -+{ -+ // loop through the whole children looking for a 'geom' element -+ QDomNode subNode = node.firstChild(); -+ while( subNode.isElement() ) -+ { -+ QDomElement e = subNode.toElement(); -+ subNode = subNode.nextSibling(); -+ if ( e.tagName() != "geom" ) -+ continue; -+ -+ // parse the attributes -+ if ( e.hasAttribute( "type" ) ) -+ setGeomType((GeomAnnotation::GeomType)e.attribute( "type" ).toInt()); -+ if ( e.hasAttribute( "color" ) ) -+ setGeomInnerColor(QColor( e.attribute( "color" ) )); -+ -+ // loading complete -+ break; -+ } -+} -+ -+GeomAnnotation::~GeomAnnotation() -+{ -+} -+ -+void GeomAnnotation::store( QDomNode & node, QDomDocument & document ) const -+{ -+ // store base annotation properties -+ storeBaseAnnotationProperties( node, document ); -+ -+ // create [geom] element -+ QDomElement geomElement = document.createElement( "geom" ); -+ node.appendChild( geomElement ); -+ -+ // append the optional attributes -+ if ( geomType() != InscribedSquare ) -+ geomElement.setAttribute( "type", (int)geomType() ); -+ if ( geomInnerColor().isValid() ) -+ geomElement.setAttribute( "color", geomInnerColor().name() ); -+} -+ -+Annotation::SubType GeomAnnotation::subType() const -+{ -+ return AGeom; -+} -+ -+GeomAnnotation::GeomType GeomAnnotation::geomType() const -+{ -+ Q_D( const GeomAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->geomType; -+ -+ if (d->pdfAnnot->getType() == Annot::typeSquare) -+ return GeomAnnotation::InscribedSquare; -+ else // Annot::typeCircle -+ return GeomAnnotation::InscribedCircle; -+} -+ -+void GeomAnnotation::setGeomType( GeomAnnotation::GeomType type ) -+{ -+ Q_D( GeomAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->geomType = type; -+ return; -+ } -+ -+ AnnotGeometry * geomann = static_cast(d->pdfAnnot); -+ if (type == GeomAnnotation::InscribedSquare) -+ geomann->setType(Annot::typeSquare); -+ else // GeomAnnotation::InscribedCircle -+ geomann->setType(Annot::typeCircle); -+} -+ -+QColor GeomAnnotation::geomInnerColor() const -+{ -+ Q_D( const GeomAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->geomInnerColor; -+ -+ const AnnotGeometry * geomann = static_cast(d->pdfAnnot); -+ return convertAnnotColor( geomann->getInteriorColor() ); -+} -+ -+void GeomAnnotation::setGeomInnerColor( const QColor &color ) -+{ -+ Q_D( GeomAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->geomInnerColor = color; -+ return; -+ } -+ -+ AnnotGeometry * geomann = static_cast(d->pdfAnnot); -+ geomann->setInteriorColor(convertQColor( color )); -+} -+ -+ -+/** HighlightAnnotation [Annotation] */ -+class HighlightAnnotationPrivate : public AnnotationPrivate -+{ -+ public: -+ HighlightAnnotationPrivate(); -+ Annotation * makeAlias(); -+ Annot* createNativeAnnot(::Page *destPage, DocumentData *doc); -+ -+ // data fields -+ HighlightAnnotation::HighlightType highlightType; -+ QList< HighlightAnnotation::Quad > highlightQuads; // not empty -+ -+ // helpers -+ static Annot::AnnotSubtype toAnnotSubType( HighlightAnnotation::HighlightType type ); -+ QList< HighlightAnnotation::Quad > fromQuadrilaterals(AnnotQuadrilaterals *quads) const; -+ AnnotQuadrilaterals * toQuadrilaterals(const QList< HighlightAnnotation::Quad > &quads) const; -+}; -+ -+HighlightAnnotationPrivate::HighlightAnnotationPrivate() -+ : AnnotationPrivate(), highlightType( HighlightAnnotation::Highlight ) -+{ -+} -+ -+Annotation * HighlightAnnotationPrivate::makeAlias() -+{ -+ return new HighlightAnnotation(*this); -+} -+ -+Annot::AnnotSubtype HighlightAnnotationPrivate::toAnnotSubType( HighlightAnnotation::HighlightType type ) -+{ -+ switch (type) -+ { -+ default: // HighlightAnnotation::Highlight: -+ return Annot::typeHighlight; -+ case HighlightAnnotation::Underline: -+ return Annot::typeUnderline; -+ case HighlightAnnotation::Squiggly: -+ return Annot::typeSquiggly; -+ case HighlightAnnotation::StrikeOut: -+ return Annot::typeStrikeOut; -+ } -+} -+ -+QList< HighlightAnnotation::Quad > HighlightAnnotationPrivate::fromQuadrilaterals(AnnotQuadrilaterals *hlquads) const -+{ -+ QList< HighlightAnnotation::Quad > quads; -+ -+ if ( !hlquads || !hlquads->getQuadrilateralsLength() ) -+ return quads; -+ const int quadsCount = hlquads->getQuadrilateralsLength(); -+ -+ double MTX[6]; -+ fillTransformationMTX(MTX); -+ -+ quads.reserve(quadsCount); -+ for (int q = 0; q < quadsCount; ++q) -+ { -+ HighlightAnnotation::Quad quad; -+ XPDFReader::transform( MTX, hlquads->getX1( q ), hlquads->getY1( q ), quad.points[ 0 ] ); -+ XPDFReader::transform( MTX, hlquads->getX2( q ), hlquads->getY2( q ), quad.points[ 1 ] ); -+ XPDFReader::transform( MTX, hlquads->getX3( q ), hlquads->getY3( q ), quad.points[ 2 ] ); -+ XPDFReader::transform( MTX, hlquads->getX4( q ), hlquads->getY4( q ), quad.points[ 3 ] ); -+ // ### PDF1.6 specs says that point are in ccw order, but in fact -+ // points 3 and 4 are swapped in every PDF around! -+ QPointF tmpPoint = quad.points[ 2 ]; -+ quad.points[ 2 ] = quad.points[ 3 ]; -+ quad.points[ 3 ] = tmpPoint; -+ // initialize other properties and append quad -+ quad.capStart = true; // unlinked quads are always capped -+ quad.capEnd = true; // unlinked quads are always capped -+ quad.feather = 0.1; // default feather -+ quads.append( quad ); -+ } -+ -+ return quads; -+} -+ -+AnnotQuadrilaterals * HighlightAnnotationPrivate::toQuadrilaterals(const QList< HighlightAnnotation::Quad > &quads) const -+{ -+ const int count = quads.size(); -+ auto ac = std::make_unique(count); -+ -+ double MTX[6]; -+ fillTransformationMTX(MTX); -+ -+ int pos = 0; -+ foreach (const HighlightAnnotation::Quad &q, quads) -+ { -+ double x1, y1, x2, y2, x3, y3, x4, y4; -+ XPDFReader::invTransform( MTX, q.points[0], x1, y1 ); -+ XPDFReader::invTransform( MTX, q.points[1], x2, y2 ); -+ // Swap points 3 and 4 (see HighlightAnnotationPrivate::fromQuadrilaterals) -+ XPDFReader::invTransform( MTX, q.points[3], x3, y3 ); -+ XPDFReader::invTransform( MTX, q.points[2], x4, y4 ); -+ ac[pos++] = AnnotQuadrilaterals::AnnotQuadrilateral(x1, y1, x2, y2, x3, y3, x4, y4); -+ } -+ -+ return new AnnotQuadrilaterals(std::move(ac), count); -+} -+ -+Annot* HighlightAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc) -+{ -+ // Setters are defined in the public class -+ HighlightAnnotation *q = static_cast( makeAlias() ); -+ -+ // Set page and document -+ pdfPage = destPage; -+ parentDoc = doc; -+ -+ // Set pdfAnnot -+ PDFRectangle rect = boundaryToPdfRectangle(boundary, flags); -+ pdfAnnot = new AnnotTextMarkup(destPage->getDoc(), &rect, toAnnotSubType(highlightType)); -+ -+ // Set properties -+ flushBaseAnnotationProperties(); -+ q->setHighlightQuads(highlightQuads); -+ -+ highlightQuads.clear(); // Free up memory -+ -+ delete q; -+ -+ return pdfAnnot; -+} -+ -+HighlightAnnotation::HighlightAnnotation() -+ : Annotation( *new HighlightAnnotationPrivate() ) -+{} -+ -+HighlightAnnotation::HighlightAnnotation(HighlightAnnotationPrivate &dd) -+ : Annotation( dd ) -+{} -+ -+HighlightAnnotation::HighlightAnnotation( const QDomNode & node ) -+ : Annotation( *new HighlightAnnotationPrivate(), node ) -+{ -+ // loop through the whole children looking for a 'hl' element -+ QDomNode subNode = node.firstChild(); -+ while( subNode.isElement() ) -+ { -+ QDomElement e = subNode.toElement(); -+ subNode = subNode.nextSibling(); -+ if ( e.tagName() != "hl" ) -+ continue; -+ -+ // parse the attributes -+ if ( e.hasAttribute( "type" ) ) -+ setHighlightType((HighlightAnnotation::HighlightType)e.attribute( "type" ).toInt()); -+ -+ // parse all 'quad' subnodes -+ QList quads; -+ QDomNode quadNode = e.firstChild(); -+ for ( ; quadNode.isElement(); quadNode = quadNode.nextSibling() ) -+ { -+ QDomElement qe = quadNode.toElement(); -+ if ( qe.tagName() != "quad" ) -+ continue; -+ -+ Quad q; -+ q.points[0].setX(qe.attribute( "ax", "0.0" ).toDouble()); -+ q.points[0].setY(qe.attribute( "ay", "0.0" ).toDouble()); -+ q.points[1].setX(qe.attribute( "bx", "0.0" ).toDouble()); -+ q.points[1].setY(qe.attribute( "by", "0.0" ).toDouble()); -+ q.points[2].setX(qe.attribute( "cx", "0.0" ).toDouble()); -+ q.points[2].setY(qe.attribute( "cy", "0.0" ).toDouble()); -+ q.points[3].setX(qe.attribute( "dx", "0.0" ).toDouble()); -+ q.points[3].setY(qe.attribute( "dy", "0.0" ).toDouble()); -+ q.capStart = qe.hasAttribute( "start" ); -+ q.capEnd = qe.hasAttribute( "end" ); -+ q.feather = qe.attribute( "feather", "0.1" ).toDouble(); -+ quads.append( q ); -+ } -+ setHighlightQuads(quads); -+ -+ // loading complete -+ break; -+ } -+} -+ -+HighlightAnnotation::~HighlightAnnotation() -+{ -+} -+ -+void HighlightAnnotation::store( QDomNode & node, QDomDocument & document ) const -+{ -+ // store base annotation properties -+ storeBaseAnnotationProperties( node, document ); -+ -+ // create [hl] element -+ QDomElement hlElement = document.createElement( "hl" ); -+ node.appendChild( hlElement ); -+ -+ // append the optional attributes -+ if ( highlightType() != Highlight ) -+ hlElement.setAttribute( "type", (int)highlightType() ); -+ -+ const QList quads = highlightQuads(); -+ if ( quads.count() < 1 ) -+ return; -+ // append highlight quads, all children describe quads -+ QList< HighlightAnnotation::Quad >::const_iterator it = quads.begin(), end = quads.end(); -+ for ( ; it != end; ++it ) -+ { -+ QDomElement quadElement = document.createElement( "quad" ); -+ hlElement.appendChild( quadElement ); -+ const Quad & q = *it; -+ quadElement.setAttribute( "ax", QString::number( q.points[0].x() ) ); -+ quadElement.setAttribute( "ay", QString::number( q.points[0].y() ) ); -+ quadElement.setAttribute( "bx", QString::number( q.points[1].x() ) ); -+ quadElement.setAttribute( "by", QString::number( q.points[1].y() ) ); -+ quadElement.setAttribute( "cx", QString::number( q.points[2].x() ) ); -+ quadElement.setAttribute( "cy", QString::number( q.points[2].y() ) ); -+ quadElement.setAttribute( "dx", QString::number( q.points[3].x() ) ); -+ quadElement.setAttribute( "dy", QString::number( q.points[3].y() ) ); -+ if ( q.capStart ) -+ quadElement.setAttribute( "start", 1 ); -+ if ( q.capEnd ) -+ quadElement.setAttribute( "end", 1 ); -+ quadElement.setAttribute( "feather", QString::number( q.feather ) ); -+ } -+} -+ -+Annotation::SubType HighlightAnnotation::subType() const -+{ -+ return AHighlight; -+} -+ -+HighlightAnnotation::HighlightType HighlightAnnotation::highlightType() const -+{ -+ Q_D( const HighlightAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->highlightType; -+ -+ Annot::AnnotSubtype subType = d->pdfAnnot->getType(); -+ -+ if ( subType == Annot::typeHighlight ) -+ return HighlightAnnotation::Highlight; -+ else if ( subType == Annot::typeUnderline ) -+ return HighlightAnnotation::Underline; -+ else if ( subType == Annot::typeSquiggly ) -+ return HighlightAnnotation::Squiggly; -+ else // Annot::typeStrikeOut -+ return HighlightAnnotation::StrikeOut; -+} -+ -+void HighlightAnnotation::setHighlightType( HighlightAnnotation::HighlightType type ) -+{ -+ Q_D( HighlightAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->highlightType = type; -+ return; -+ } -+ -+ AnnotTextMarkup * hlann = static_cast(d->pdfAnnot); -+ hlann->setType(HighlightAnnotationPrivate::toAnnotSubType( type )); -+} -+ -+QList< HighlightAnnotation::Quad > HighlightAnnotation::highlightQuads() const -+{ -+ Q_D( const HighlightAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->highlightQuads; -+ -+ const AnnotTextMarkup * hlann = static_cast(d->pdfAnnot); -+ return d->fromQuadrilaterals( hlann->getQuadrilaterals() ); -+} -+ -+void HighlightAnnotation::setHighlightQuads( const QList< HighlightAnnotation::Quad > &quads ) -+{ -+ Q_D( HighlightAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->highlightQuads = quads; -+ return; -+ } -+ -+ AnnotTextMarkup * hlann = static_cast(d->pdfAnnot); -+ AnnotQuadrilaterals * quadrilaterals = d->toQuadrilaterals(quads); -+ hlann->setQuadrilaterals(quadrilaterals); -+ delete quadrilaterals; -+} -+ -+ -+/** StampAnnotation [Annotation] */ -+class StampAnnotationPrivate : public AnnotationPrivate -+{ -+ public: -+ StampAnnotationPrivate(); -+ Annotation * makeAlias(); -+ Annot* createNativeAnnot(::Page *destPage, DocumentData *doc); -+ -+ // data fields -+ QString stampIconName; -+}; -+ -+StampAnnotationPrivate::StampAnnotationPrivate() -+ : AnnotationPrivate(), stampIconName( "Draft" ) -+{ -+} -+ -+Annotation * StampAnnotationPrivate::makeAlias() -+{ -+ return new StampAnnotation(*this); -+} -+ -+Annot* StampAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc) -+{ -+ StampAnnotation *q = static_cast( makeAlias() ); -+ -+ // Set page and document -+ pdfPage = destPage; -+ parentDoc = doc; -+ -+ // Set pdfAnnot -+ PDFRectangle rect = boundaryToPdfRectangle(boundary, flags); -+ pdfAnnot = new AnnotStamp(destPage->getDoc(), &rect); -+ -+ // Set properties -+ flushBaseAnnotationProperties(); -+ q->setStampIconName(stampIconName); -+ -+ delete q; -+ -+ stampIconName.clear(); // Free up memory -+ -+ return pdfAnnot; -+} -+ -+StampAnnotation::StampAnnotation() -+ : Annotation( *new StampAnnotationPrivate() ) -+{} -+ -+StampAnnotation::StampAnnotation(StampAnnotationPrivate &dd) -+ : Annotation( dd ) -+{} -+ -+StampAnnotation::StampAnnotation( const QDomNode & node ) -+ : Annotation( *new StampAnnotationPrivate(), node ) -+{ -+ // loop through the whole children looking for a 'stamp' element -+ QDomNode subNode = node.firstChild(); -+ while( subNode.isElement() ) -+ { -+ QDomElement e = subNode.toElement(); -+ subNode = subNode.nextSibling(); -+ if ( e.tagName() != "stamp" ) -+ continue; -+ -+ // parse the attributes -+ if ( e.hasAttribute( "icon" ) ) -+ setStampIconName(e.attribute( "icon" )); -+ -+ // loading complete -+ break; -+ } -+} -+ -+StampAnnotation::~StampAnnotation() -+{ -+} -+ -+void StampAnnotation::store( QDomNode & node, QDomDocument & document ) const -+{ -+ // store base annotation properties -+ storeBaseAnnotationProperties( node, document ); -+ -+ // create [stamp] element -+ QDomElement stampElement = document.createElement( "stamp" ); -+ node.appendChild( stampElement ); -+ -+ // append the optional attributes -+ if ( stampIconName() != "Draft" ) -+ stampElement.setAttribute( "icon", stampIconName() ); -+} -+ -+Annotation::SubType StampAnnotation::subType() const -+{ -+ return AStamp; -+} -+ -+QString StampAnnotation::stampIconName() const -+{ -+ Q_D( const StampAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->stampIconName; -+ -+ const AnnotStamp * stampann = static_cast(d->pdfAnnot); -+ return QString::fromLatin1( stampann->getIcon()->c_str() ); -+} -+ -+void StampAnnotation::setStampIconName( const QString &name ) -+{ -+ Q_D( StampAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->stampIconName = name; -+ return; -+ } -+ -+ AnnotStamp * stampann = static_cast(d->pdfAnnot); -+ QByteArray encoded = name.toLatin1(); -+ GooString s(encoded.constData()); -+ stampann->setIcon(&s); -+} -+ -+/** InkAnnotation [Annotation] */ -+class InkAnnotationPrivate : public AnnotationPrivate -+{ -+ public: -+ InkAnnotationPrivate(); -+ Annotation * makeAlias(); -+ Annot* createNativeAnnot(::Page *destPage, DocumentData *doc); -+ -+ // data fields -+ QList< QLinkedList > inkPaths; -+ -+ // helper -+ AnnotPath **toAnnotPaths(const QList< QLinkedList > &inkPaths); -+}; -+ -+InkAnnotationPrivate::InkAnnotationPrivate() -+ : AnnotationPrivate() -+{ -+} -+ -+Annotation * InkAnnotationPrivate::makeAlias() -+{ -+ return new InkAnnotation(*this); -+} -+ -+// Note: Caller is required to delete array elements and the array itself after use -+AnnotPath **InkAnnotationPrivate::toAnnotPaths(const QList< QLinkedList > &inkPaths) -+{ -+ const int pathsNumber = inkPaths.size(); -+ AnnotPath **res = new AnnotPath*[pathsNumber]; -+ for (int i = 0; i < pathsNumber; ++i) -+ res[i] = toAnnotPath( inkPaths[i] ); -+ return res; -+} -+ -+Annot* InkAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc) -+{ -+ // Setters are defined in the public class -+ InkAnnotation *q = static_cast( makeAlias() ); -+ -+ // Set page and document -+ pdfPage = destPage; -+ parentDoc = doc; -+ -+ // Set pdfAnnot -+ PDFRectangle rect = boundaryToPdfRectangle(boundary, flags); -+ pdfAnnot = new AnnotInk(destPage->getDoc(), &rect); -+ -+ // Set properties -+ flushBaseAnnotationProperties(); -+ q->setInkPaths(inkPaths); -+ -+ inkPaths.clear(); // Free up memory -+ -+ delete q; -+ -+ return pdfAnnot; -+} -+ -+InkAnnotation::InkAnnotation() -+ : Annotation( *new InkAnnotationPrivate() ) -+{} -+ -+InkAnnotation::InkAnnotation(InkAnnotationPrivate &dd) -+ : Annotation( dd ) -+{} -+ -+InkAnnotation::InkAnnotation( const QDomNode & node ) -+ : Annotation( *new InkAnnotationPrivate(), node ) -+{ -+ // loop through the whole children looking for a 'ink' element -+ QDomNode subNode = node.firstChild(); -+ while( subNode.isElement() ) -+ { -+ QDomElement e = subNode.toElement(); -+ subNode = subNode.nextSibling(); -+ if ( e.tagName() != "ink" ) -+ continue; -+ -+ // parse the 'path' subnodes -+ QList< QLinkedList > paths; -+ QDomNode pathNode = e.firstChild(); -+ while ( pathNode.isElement() ) -+ { -+ QDomElement pathElement = pathNode.toElement(); -+ pathNode = pathNode.nextSibling(); -+ -+ if ( pathElement.tagName() != "path" ) -+ continue; -+ -+ // build each path parsing 'point' subnodes -+ QLinkedList path; -+ QDomNode pointNode = pathElement.firstChild(); -+ while ( pointNode.isElement() ) -+ { -+ QDomElement pointElement = pointNode.toElement(); -+ pointNode = pointNode.nextSibling(); -+ -+ if ( pointElement.tagName() != "point" ) -+ continue; -+ -+ QPointF p(pointElement.attribute( "x", "0.0" ).toDouble(), pointElement.attribute( "y", "0.0" ).toDouble()); -+ path.append( p ); -+ } -+ -+ // add the path to the path list if it contains at least 2 nodes -+ if ( path.count() >= 2 ) -+ paths.append( path ); -+ } -+ setInkPaths(paths); -+ -+ // loading complete -+ break; -+ } -+} -+ -+InkAnnotation::~InkAnnotation() -+{ -+} -+ -+void InkAnnotation::store( QDomNode & node, QDomDocument & document ) const -+{ -+ // store base annotation properties -+ storeBaseAnnotationProperties( node, document ); -+ -+ // create [ink] element -+ QDomElement inkElement = document.createElement( "ink" ); -+ node.appendChild( inkElement ); -+ -+ // append the optional attributes -+ const QList< QLinkedList > paths = inkPaths(); -+ if ( paths.count() < 1 ) -+ return; -+ QList< QLinkedList >::const_iterator pIt = paths.begin(), pEnd = paths.end(); -+ for ( ; pIt != pEnd; ++pIt ) -+ { -+ QDomElement pathElement = document.createElement( "path" ); -+ inkElement.appendChild( pathElement ); -+ const QLinkedList & path = *pIt; -+ QLinkedList::const_iterator iIt = path.begin(), iEnd = path.end(); -+ for ( ; iIt != iEnd; ++iIt ) -+ { -+ const QPointF & point = *iIt; -+ QDomElement pointElement = document.createElement( "point" ); -+ pathElement.appendChild( pointElement ); -+ pointElement.setAttribute( "x", QString::number( point.x() ) ); -+ pointElement.setAttribute( "y", QString::number( point.y() ) ); -+ } -+ } -+} -+ -+Annotation::SubType InkAnnotation::subType() const -+{ -+ return AInk; -+} -+ -+QList< QLinkedList > InkAnnotation::inkPaths() const -+{ -+ Q_D( const InkAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->inkPaths; -+ -+ const AnnotInk * inkann = static_cast(d->pdfAnnot); -+ -+ const AnnotPath * const* paths = inkann->getInkList(); -+ if ( !paths || !inkann->getInkListLength() ) -+ return QList< QLinkedList >(); -+ -+ double MTX[6]; -+ d->fillTransformationMTX(MTX); -+ -+ const int pathsNumber = inkann->getInkListLength(); -+ QList< QLinkedList > inkPaths; -+ inkPaths.reserve(pathsNumber); -+ for (int m = 0; m < pathsNumber; ++m) -+ { -+ // transform each path in a list of normalized points .. -+ QLinkedList localList; -+ const AnnotPath * path = paths[ m ]; -+ const int pointsNumber = path ? path->getCoordsLength() : 0; -+ for (int n = 0; n < pointsNumber; ++n) -+ { -+ QPointF point; -+ XPDFReader::transform(MTX, path->getX(n), path->getY(n), point); -+ localList.append(point); -+ } -+ // ..and add it to the annotation -+ inkPaths.append( localList ); -+ } -+ return inkPaths; -+} -+ -+void InkAnnotation::setInkPaths( const QList< QLinkedList > &paths ) -+{ -+ Q_D( InkAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->inkPaths = paths; -+ return; -+ } -+ -+ AnnotInk * inkann = static_cast(d->pdfAnnot); -+ AnnotPath **annotpaths = d->toAnnotPaths(paths); -+ const int pathsNumber = paths.size(); -+ inkann->setInkList(annotpaths, pathsNumber); -+ -+ for (int i = 0; i < pathsNumber; ++i) -+ delete annotpaths[i]; -+ delete[] annotpaths; -+} -+ -+ -+/** LinkAnnotation [Annotation] */ -+class LinkAnnotationPrivate : public AnnotationPrivate -+{ -+ public: -+ LinkAnnotationPrivate(); -+ ~LinkAnnotationPrivate(); -+ Annotation * makeAlias(); -+ Annot* createNativeAnnot(::Page *destPage, DocumentData *doc); -+ -+ // data fields -+ Link * linkDestination; -+ LinkAnnotation::HighlightMode linkHLMode; -+ QPointF linkRegion[4]; -+}; -+ -+LinkAnnotationPrivate::LinkAnnotationPrivate() -+ : AnnotationPrivate(), linkDestination( nullptr ), linkHLMode( LinkAnnotation::Invert ) -+{ -+} -+ -+LinkAnnotationPrivate::~LinkAnnotationPrivate() -+{ -+ delete linkDestination; -+} -+ -+Annotation * LinkAnnotationPrivate::makeAlias() -+{ -+ return new LinkAnnotation(*this); -+} -+ -+Annot* LinkAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc) -+{ -+ return nullptr; // Not implemented -+} -+ -+LinkAnnotation::LinkAnnotation() -+ : Annotation( *new LinkAnnotationPrivate() ) -+{} -+ -+LinkAnnotation::LinkAnnotation(LinkAnnotationPrivate &dd) -+ : Annotation( dd ) -+{} -+ -+LinkAnnotation::LinkAnnotation( const QDomNode & node ) -+ : Annotation( *new LinkAnnotationPrivate(), node ) -+{ -+ // loop through the whole children looking for a 'link' element -+ QDomNode subNode = node.firstChild(); -+ while( subNode.isElement() ) -+ { -+ QDomElement e = subNode.toElement(); -+ subNode = subNode.nextSibling(); -+ if ( e.tagName() != "link" ) -+ continue; -+ -+ // parse the attributes -+ if ( e.hasAttribute( "hlmode" ) ) -+ setLinkHighlightMode((LinkAnnotation::HighlightMode)e.attribute( "hlmode" ).toInt()); -+ -+ // parse all 'quad' subnodes -+ QDomNode quadNode = e.firstChild(); -+ for ( ; quadNode.isElement(); quadNode = quadNode.nextSibling() ) -+ { -+ QDomElement qe = quadNode.toElement(); -+ if ( qe.tagName() == "quad" ) -+ { -+ setLinkRegionPoint(0, QPointF(qe.attribute( "ax", "0.0" ).toDouble(), -+ qe.attribute( "ay", "0.0" ).toDouble())); -+ setLinkRegionPoint(1, QPointF(qe.attribute( "bx", "0.0" ).toDouble(), -+ qe.attribute( "by", "0.0" ).toDouble())); -+ setLinkRegionPoint(2, QPointF(qe.attribute( "cx", "0.0" ).toDouble(), -+ qe.attribute( "cy", "0.0" ).toDouble())); -+ setLinkRegionPoint(3, QPointF(qe.attribute( "dx", "0.0" ).toDouble(), -+ qe.attribute( "dy", "0.0" ).toDouble())); -+ } -+ else if ( qe.tagName() == "link" ) -+ { -+ QString type = qe.attribute( "type" ); -+ if ( type == "GoTo" ) -+ { -+ Poppler::LinkGoto * go = new Poppler::LinkGoto( QRect(), qe.attribute( "filename" ), LinkDestination( qe.attribute( "destination" ) ) ); -+ setLinkDestination(go); -+ } -+ else if ( type == "Exec" ) -+ { -+ Poppler::LinkExecute * exec = new Poppler::LinkExecute( QRect(), qe.attribute( "filename" ), qe.attribute( "parameters" ) ); -+ setLinkDestination(exec); -+ } -+ else if ( type == "Browse" ) -+ { -+ Poppler::LinkBrowse * browse = new Poppler::LinkBrowse( QRect(), qe.attribute( "url" ) ); -+ setLinkDestination(browse); -+ } -+ else if ( type == "Action" ) -+ { -+ Poppler::LinkAction::ActionType act; -+ QString actString = qe.attribute( "action" ); -+ bool found = true; -+ if ( actString == "PageFirst" ) -+ act = Poppler::LinkAction::PageFirst; -+ else if ( actString == "PagePrev" ) -+ act = Poppler::LinkAction::PagePrev; -+ else if ( actString == "PageNext" ) -+ act = Poppler::LinkAction::PageNext; -+ else if ( actString == "PageLast" ) -+ act = Poppler::LinkAction::PageLast; -+ else if ( actString == "HistoryBack" ) -+ act = Poppler::LinkAction::HistoryBack; -+ else if ( actString == "HistoryForward" ) -+ act = Poppler::LinkAction::HistoryForward; -+ else if ( actString == "Quit" ) -+ act = Poppler::LinkAction::Quit; -+ else if ( actString == "Presentation" ) -+ act = Poppler::LinkAction::Presentation; -+ else if ( actString == "EndPresentation" ) -+ act = Poppler::LinkAction::EndPresentation; -+ else if ( actString == "Find" ) -+ act = Poppler::LinkAction::Find; -+ else if ( actString == "GoToPage" ) -+ act = Poppler::LinkAction::GoToPage; -+ else if ( actString == "Close" ) -+ act = Poppler::LinkAction::Close; -+ else if ( actString == "Print" ) -+ act = Poppler::LinkAction::Print; -+ else -+ found = false; -+ if (found) -+ { -+ Poppler::LinkAction * action = new Poppler::LinkAction( QRect(), act ); -+ setLinkDestination(action); -+ } -+ } -+#if 0 -+ else if ( type == "Movie" ) -+ { -+ Poppler::LinkMovie * movie = new Poppler::LinkMovie( QRect() ); -+ setLinkDestination(movie); -+ } -+#endif -+ } -+ } -+ -+ // loading complete -+ break; -+ } -+} -+ -+LinkAnnotation::~LinkAnnotation() -+{ -+} -+ -+void LinkAnnotation::store( QDomNode & node, QDomDocument & document ) const -+{ -+ // store base annotation properties -+ storeBaseAnnotationProperties( node, document ); -+ -+ // create [hl] element -+ QDomElement linkElement = document.createElement( "link" ); -+ node.appendChild( linkElement ); -+ -+ // append the optional attributes -+ if ( linkHighlightMode() != Invert ) -+ linkElement.setAttribute( "hlmode", (int)linkHighlightMode() ); -+ -+ // saving region -+ QDomElement quadElement = document.createElement( "quad" ); -+ linkElement.appendChild( quadElement ); -+ quadElement.setAttribute( "ax", QString::number( linkRegionPoint(0).x() ) ); -+ quadElement.setAttribute( "ay", QString::number( linkRegionPoint(0).y() ) ); -+ quadElement.setAttribute( "bx", QString::number( linkRegionPoint(1).x() ) ); -+ quadElement.setAttribute( "by", QString::number( linkRegionPoint(1).y() ) ); -+ quadElement.setAttribute( "cx", QString::number( linkRegionPoint(2).x() ) ); -+ quadElement.setAttribute( "cy", QString::number( linkRegionPoint(2).y() ) ); -+ quadElement.setAttribute( "dx", QString::number( linkRegionPoint(3).x() ) ); -+ quadElement.setAttribute( "dy", QString::number( linkRegionPoint(3).y() ) ); -+ -+ // saving link -+ QDomElement hyperlinkElement = document.createElement( "link" ); -+ linkElement.appendChild( hyperlinkElement ); -+ if ( linkDestination() ) -+ { -+ switch( linkDestination()->linkType() ) -+ { -+ case Poppler::Link::Goto: -+ { -+ Poppler::LinkGoto * go = static_cast< Poppler::LinkGoto * >( linkDestination() ); -+ hyperlinkElement.setAttribute( "type", "GoTo" ); -+ hyperlinkElement.setAttribute( "filename", go->fileName() ); -+ hyperlinkElement.setAttribute( "destionation", go->destination().toString() ); // TODO Remove for poppler 0.28 -+ hyperlinkElement.setAttribute( "destination", go->destination().toString() ); -+ break; -+ } -+ case Poppler::Link::Execute: -+ { -+ Poppler::LinkExecute * exec = static_cast< Poppler::LinkExecute * >( linkDestination() ); -+ hyperlinkElement.setAttribute( "type", "Exec" ); -+ hyperlinkElement.setAttribute( "filename", exec->fileName() ); -+ hyperlinkElement.setAttribute( "parameters", exec->parameters() ); -+ break; -+ } -+ case Poppler::Link::Browse: -+ { -+ Poppler::LinkBrowse * browse = static_cast< Poppler::LinkBrowse * >( linkDestination() ); -+ hyperlinkElement.setAttribute( "type", "Browse" ); -+ hyperlinkElement.setAttribute( "url", browse->url() ); -+ break; -+ } -+ case Poppler::Link::Action: -+ { -+ Poppler::LinkAction * action = static_cast< Poppler::LinkAction * >( linkDestination() ); -+ hyperlinkElement.setAttribute( "type", "Action" ); -+ switch ( action->actionType() ) -+ { -+ case Poppler::LinkAction::PageFirst: -+ hyperlinkElement.setAttribute( "action", "PageFirst" ); -+ break; -+ case Poppler::LinkAction::PagePrev: -+ hyperlinkElement.setAttribute( "action", "PagePrev" ); -+ break; -+ case Poppler::LinkAction::PageNext: -+ hyperlinkElement.setAttribute( "action", "PageNext" ); -+ break; -+ case Poppler::LinkAction::PageLast: -+ hyperlinkElement.setAttribute( "action", "PageLast" ); -+ break; -+ case Poppler::LinkAction::HistoryBack: -+ hyperlinkElement.setAttribute( "action", "HistoryBack" ); -+ break; -+ case Poppler::LinkAction::HistoryForward: -+ hyperlinkElement.setAttribute( "action", "HistoryForward" ); -+ break; -+ case Poppler::LinkAction::Quit: -+ hyperlinkElement.setAttribute( "action", "Quit" ); -+ break; -+ case Poppler::LinkAction::Presentation: -+ hyperlinkElement.setAttribute( "action", "Presentation" ); -+ break; -+ case Poppler::LinkAction::EndPresentation: -+ hyperlinkElement.setAttribute( "action", "EndPresentation" ); -+ break; -+ case Poppler::LinkAction::Find: -+ hyperlinkElement.setAttribute( "action", "Find" ); -+ break; -+ case Poppler::LinkAction::GoToPage: -+ hyperlinkElement.setAttribute( "action", "GoToPage" ); -+ break; -+ case Poppler::LinkAction::Close: -+ hyperlinkElement.setAttribute( "action", "Close" ); -+ break; -+ case Poppler::LinkAction::Print: -+ hyperlinkElement.setAttribute( "action", "Print" ); -+ break; -+ } -+ break; -+ } -+ case Poppler::Link::Movie: -+ { -+ hyperlinkElement.setAttribute( "type", "Movie" ); -+ break; -+ } -+ case Poppler::Link::Rendition: -+ { -+ hyperlinkElement.setAttribute( "type", "Rendition" ); -+ break; -+ } -+ case Poppler::Link::Sound: -+ { -+ // FIXME: implement me -+ break; -+ } -+ case Poppler::Link::None: -+ break; -+ } -+ } -+} -+ -+Annotation::SubType LinkAnnotation::subType() const -+{ -+ return ALink; -+} -+ -+Link* LinkAnnotation::linkDestination() const -+{ -+ Q_D( const LinkAnnotation ); -+ return d->linkDestination; -+} -+ -+void LinkAnnotation::setLinkDestination( Link *link ) -+{ -+ Q_D( LinkAnnotation ); -+ delete d->linkDestination; -+ d->linkDestination = link; -+} -+ -+LinkAnnotation::HighlightMode LinkAnnotation::linkHighlightMode() const -+{ -+ Q_D( const LinkAnnotation ); -+ return d->linkHLMode; -+} -+ -+void LinkAnnotation::setLinkHighlightMode( LinkAnnotation::HighlightMode mode ) -+{ -+ Q_D( LinkAnnotation ); -+ d->linkHLMode = mode; -+} -+ -+QPointF LinkAnnotation::linkRegionPoint( int id ) const -+{ -+ if ( id < 0 || id >= 4 ) -+ return QPointF(); -+ -+ Q_D( const LinkAnnotation ); -+ return d->linkRegion[id]; -+} -+ -+void LinkAnnotation::setLinkRegionPoint( int id, const QPointF &point ) -+{ -+ if ( id < 0 || id >= 4 ) -+ return; -+ -+ Q_D( LinkAnnotation ); -+ d->linkRegion[id] = point; -+} -+ -+/** CaretAnnotation [Annotation] */ -+class CaretAnnotationPrivate : public AnnotationPrivate -+{ -+ public: -+ CaretAnnotationPrivate(); -+ Annotation * makeAlias(); -+ Annot* createNativeAnnot(::Page *destPage, DocumentData *doc); -+ -+ // data fields -+ CaretAnnotation::CaretSymbol symbol; -+}; -+ -+static QString caretSymbolToString( CaretAnnotation::CaretSymbol symbol ) -+{ -+ switch ( symbol ) -+ { -+ case CaretAnnotation::None: -+ return QString::fromLatin1( "None" ); -+ case CaretAnnotation::P: -+ return QString::fromLatin1( "P" ); -+ } -+ return QString(); -+} -+ -+static CaretAnnotation::CaretSymbol caretSymbolFromString( const QString &symbol ) -+{ -+ if ( symbol == QLatin1String( "None" ) ) -+ return CaretAnnotation::None; -+ else if ( symbol == QLatin1String( "P" ) ) -+ return CaretAnnotation::P; -+ return CaretAnnotation::None; -+} -+ -+CaretAnnotationPrivate::CaretAnnotationPrivate() -+ : AnnotationPrivate(), symbol( CaretAnnotation::None ) -+{ -+} -+ -+Annotation * CaretAnnotationPrivate::makeAlias() -+{ -+ return new CaretAnnotation(*this); -+} -+ -+Annot* CaretAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc) -+{ -+ // Setters are defined in the public class -+ CaretAnnotation *q = static_cast( makeAlias() ); -+ -+ // Set page and document -+ pdfPage = destPage; -+ parentDoc = doc; -+ -+ // Set pdfAnnot -+ PDFRectangle rect = boundaryToPdfRectangle(boundary, flags); -+ pdfAnnot = new AnnotCaret(destPage->getDoc(), &rect); -+ -+ // Set properties -+ flushBaseAnnotationProperties(); -+ q->setCaretSymbol(symbol); -+ -+ delete q; -+ return pdfAnnot; -+} -+ -+CaretAnnotation::CaretAnnotation() -+ : Annotation( *new CaretAnnotationPrivate() ) -+{ -+} -+ -+CaretAnnotation::CaretAnnotation(CaretAnnotationPrivate &dd) -+ : Annotation( dd ) -+{ -+} -+ -+CaretAnnotation::CaretAnnotation( const QDomNode & node ) -+ : Annotation( *new CaretAnnotationPrivate(), node ) -+{ -+ // loop through the whole children looking for a 'caret' element -+ QDomNode subNode = node.firstChild(); -+ while( subNode.isElement() ) -+ { -+ QDomElement e = subNode.toElement(); -+ subNode = subNode.nextSibling(); -+ if ( e.tagName() != "caret" ) -+ continue; -+ -+ // parse the attributes -+ if ( e.hasAttribute( "symbol" ) ) -+ setCaretSymbol(caretSymbolFromString( e.attribute( "symbol" ) )); -+ -+ // loading complete -+ break; -+ } -+} -+ -+CaretAnnotation::~CaretAnnotation() -+{ -+} -+ -+void CaretAnnotation::store( QDomNode & node, QDomDocument & document ) const -+{ -+ // store base annotation properties -+ storeBaseAnnotationProperties( node, document ); -+ -+ // create [caret] element -+ QDomElement caretElement = document.createElement( "caret" ); -+ node.appendChild( caretElement ); -+ -+ // append the optional attributes -+ if ( caretSymbol() != CaretAnnotation::None ) -+ caretElement.setAttribute( "symbol", caretSymbolToString( caretSymbol() ) ); -+} -+ -+Annotation::SubType CaretAnnotation::subType() const -+{ -+ return ACaret; -+} -+ -+CaretAnnotation::CaretSymbol CaretAnnotation::caretSymbol() const -+{ -+ Q_D( const CaretAnnotation ); -+ -+ if (!d->pdfAnnot) -+ return d->symbol; -+ -+ const AnnotCaret * caretann = static_cast(d->pdfAnnot); -+ return (CaretAnnotation::CaretSymbol)caretann->getSymbol(); -+} -+ -+void CaretAnnotation::setCaretSymbol( CaretAnnotation::CaretSymbol symbol ) -+{ -+ Q_D( CaretAnnotation ); -+ -+ if (!d->pdfAnnot) -+ { -+ d->symbol = symbol; -+ return; -+ } -+ -+ AnnotCaret * caretann = static_cast(d->pdfAnnot); -+ caretann->setSymbol((AnnotCaret::AnnotCaretSymbol)symbol); -+} -+ -+/** FileAttachmentAnnotation [Annotation] */ -+class FileAttachmentAnnotationPrivate : public AnnotationPrivate -+{ -+ public: -+ FileAttachmentAnnotationPrivate(); -+ ~FileAttachmentAnnotationPrivate(); -+ Annotation * makeAlias(); -+ Annot* createNativeAnnot(::Page *destPage, DocumentData *doc); -+ -+ // data fields -+ QString icon; -+ EmbeddedFile *embfile; -+}; -+ -+FileAttachmentAnnotationPrivate::FileAttachmentAnnotationPrivate() -+ : AnnotationPrivate(), icon( "PushPin" ), embfile( nullptr ) -+{ -+} -+ -+FileAttachmentAnnotationPrivate::~FileAttachmentAnnotationPrivate() -+{ -+ delete embfile; -+} -+ -+Annotation * FileAttachmentAnnotationPrivate::makeAlias() -+{ -+ return new FileAttachmentAnnotation(*this); -+} -+ -+Annot* FileAttachmentAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc) -+{ -+ return nullptr; // Not implemented -+} -+ -+FileAttachmentAnnotation::FileAttachmentAnnotation() -+ : Annotation( *new FileAttachmentAnnotationPrivate() ) -+{ -+} -+ -+FileAttachmentAnnotation::FileAttachmentAnnotation(FileAttachmentAnnotationPrivate &dd) -+ : Annotation( dd ) -+{ -+} -+ -+FileAttachmentAnnotation::FileAttachmentAnnotation( const QDomNode & node ) -+ : Annotation( *new FileAttachmentAnnotationPrivate(), node ) -+{ -+ // loop through the whole children looking for a 'fileattachment' element -+ QDomNode subNode = node.firstChild(); -+ while( subNode.isElement() ) -+ { -+ QDomElement e = subNode.toElement(); -+ subNode = subNode.nextSibling(); -+ if ( e.tagName() != "fileattachment" ) -+ continue; -+ -+ // loading complete -+ break; -+ } -+} -+ -+FileAttachmentAnnotation::~FileAttachmentAnnotation() -+{ -+} -+ -+void FileAttachmentAnnotation::store( QDomNode & node, QDomDocument & document ) const -+{ -+ // store base annotation properties -+ storeBaseAnnotationProperties( node, document ); -+ -+ // create [fileattachment] element -+ QDomElement fileAttachmentElement = document.createElement( "fileattachment" ); -+ node.appendChild( fileAttachmentElement ); -+} -+ -+Annotation::SubType FileAttachmentAnnotation::subType() const -+{ -+ return AFileAttachment; -+} -+ -+QString FileAttachmentAnnotation::fileIconName() const -+{ -+ Q_D( const FileAttachmentAnnotation ); -+ return d->icon; -+} -+ -+void FileAttachmentAnnotation::setFileIconName( const QString &icon ) -+{ -+ Q_D( FileAttachmentAnnotation ); -+ d->icon = icon; -+} -+ -+EmbeddedFile* FileAttachmentAnnotation::embeddedFile() const -+{ -+ Q_D( const FileAttachmentAnnotation ); -+ return d->embfile; -+} -+ -+void FileAttachmentAnnotation::setEmbeddedFile( EmbeddedFile *ef ) -+{ -+ Q_D( FileAttachmentAnnotation ); -+ d->embfile = ef; -+} -+ -+/** SoundAnnotation [Annotation] */ -+class SoundAnnotationPrivate : public AnnotationPrivate -+{ -+ public: -+ SoundAnnotationPrivate(); -+ ~SoundAnnotationPrivate(); -+ Annotation * makeAlias(); -+ Annot* createNativeAnnot(::Page *destPage, DocumentData *doc); -+ -+ // data fields -+ QString icon; -+ SoundObject *sound; -+}; -+ -+SoundAnnotationPrivate::SoundAnnotationPrivate() -+ : AnnotationPrivate(), icon( "Speaker" ), sound( nullptr ) -+{ -+} -+ -+SoundAnnotationPrivate::~SoundAnnotationPrivate() -+{ -+ delete sound; -+} -+ -+Annotation * SoundAnnotationPrivate::makeAlias() -+{ -+ return new SoundAnnotation(*this); -+} -+ -+Annot* SoundAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc) -+{ -+ return nullptr; // Not implemented -+} -+ -+SoundAnnotation::SoundAnnotation() -+ : Annotation( *new SoundAnnotationPrivate() ) -+{ -+} -+ -+SoundAnnotation::SoundAnnotation(SoundAnnotationPrivate &dd) -+ : Annotation( dd ) -+{ -+} -+ -+SoundAnnotation::SoundAnnotation( const QDomNode & node ) -+ : Annotation( *new SoundAnnotationPrivate(), node ) -+{ -+ // loop through the whole children looking for a 'sound' element -+ QDomNode subNode = node.firstChild(); -+ while( subNode.isElement() ) -+ { -+ QDomElement e = subNode.toElement(); -+ subNode = subNode.nextSibling(); -+ if ( e.tagName() != "sound" ) -+ continue; -+ -+ // loading complete -+ break; -+ } -+} -+ -+SoundAnnotation::~SoundAnnotation() -+{ -+} -+ -+void SoundAnnotation::store( QDomNode & node, QDomDocument & document ) const -+{ -+ // store base annotation properties -+ storeBaseAnnotationProperties( node, document ); -+ -+ // create [sound] element -+ QDomElement soundElement = document.createElement( "sound" ); -+ node.appendChild( soundElement ); -+} -+ -+Annotation::SubType SoundAnnotation::subType() const -+{ -+ return ASound; -+} -+ -+QString SoundAnnotation::soundIconName() const -+{ -+ Q_D( const SoundAnnotation ); -+ return d->icon; -+} -+ -+void SoundAnnotation::setSoundIconName( const QString &icon ) -+{ -+ Q_D( SoundAnnotation ); -+ d->icon = icon; -+} -+ -+SoundObject* SoundAnnotation::sound() const -+{ -+ Q_D( const SoundAnnotation ); -+ return d->sound; -+} -+ -+void SoundAnnotation::setSound( SoundObject *s ) -+{ -+ Q_D( SoundAnnotation ); -+ d->sound = s; -+} -+ -+/** MovieAnnotation [Annotation] */ -+class MovieAnnotationPrivate : public AnnotationPrivate -+{ -+ public: -+ MovieAnnotationPrivate(); -+ ~MovieAnnotationPrivate(); -+ Annotation * makeAlias(); -+ Annot* createNativeAnnot(::Page *destPage, DocumentData *doc); -+ -+ // data fields -+ MovieObject *movie; -+ QString title; -+}; -+ -+MovieAnnotationPrivate::MovieAnnotationPrivate() -+ : AnnotationPrivate(), movie( nullptr ) -+{ -+} -+ -+MovieAnnotationPrivate::~MovieAnnotationPrivate() -+{ -+ delete movie; -+} -+ -+Annotation * MovieAnnotationPrivate::makeAlias() -+{ -+ return new MovieAnnotation(*this); -+} -+ -+Annot* MovieAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc) -+{ -+ return nullptr; // Not implemented -+} -+ -+MovieAnnotation::MovieAnnotation() -+ : Annotation( *new MovieAnnotationPrivate() ) -+{ -+} -+ -+MovieAnnotation::MovieAnnotation(MovieAnnotationPrivate &dd) -+ : Annotation( dd ) -+{ -+} -+ -+MovieAnnotation::MovieAnnotation( const QDomNode & node ) -+ : Annotation( *new MovieAnnotationPrivate(), node ) -+{ -+ // loop through the whole children looking for a 'movie' element -+ QDomNode subNode = node.firstChild(); -+ while( subNode.isElement() ) -+ { -+ QDomElement e = subNode.toElement(); -+ subNode = subNode.nextSibling(); -+ if ( e.tagName() != "movie" ) -+ continue; -+ -+ // loading complete -+ break; -+ } -+} -+ -+MovieAnnotation::~MovieAnnotation() -+{ -+} -+ -+void MovieAnnotation::store( QDomNode & node, QDomDocument & document ) const -+{ -+ // store base annotation properties -+ storeBaseAnnotationProperties( node, document ); -+ -+ // create [movie] element -+ QDomElement movieElement = document.createElement( "movie" ); -+ node.appendChild( movieElement ); -+} -+ -+Annotation::SubType MovieAnnotation::subType() const -+{ -+ return AMovie; -+} -+ -+MovieObject* MovieAnnotation::movie() const -+{ -+ Q_D( const MovieAnnotation ); -+ return d->movie; -+} -+ -+void MovieAnnotation::setMovie( MovieObject *movie ) -+{ -+ Q_D( MovieAnnotation ); -+ d->movie = movie; -+} -+ -+QString MovieAnnotation::movieTitle() const -+{ -+ Q_D( const MovieAnnotation ); -+ return d->title; -+} -+ -+void MovieAnnotation::setMovieTitle( const QString &title ) -+{ -+ Q_D( MovieAnnotation ); -+ d->title = title; -+} -+ -+/** ScreenAnnotation [Annotation] */ -+class ScreenAnnotationPrivate : public AnnotationPrivate -+{ -+ public: -+ ScreenAnnotationPrivate(); -+ ~ScreenAnnotationPrivate(); -+ Annotation * makeAlias(); -+ Annot* createNativeAnnot(::Page *destPage, DocumentData *doc); -+ -+ // data fields -+ LinkRendition *action; -+ QString title; -+}; -+ -+ScreenAnnotationPrivate::ScreenAnnotationPrivate() -+ : AnnotationPrivate(), action( nullptr ) -+{ -+} -+ -+ScreenAnnotationPrivate::~ScreenAnnotationPrivate() -+{ -+ delete action; -+} -+ -+ScreenAnnotation::ScreenAnnotation(ScreenAnnotationPrivate &dd) -+ : Annotation( dd ) -+{} -+ -+Annotation * ScreenAnnotationPrivate::makeAlias() -+{ -+ return new ScreenAnnotation(*this); -+} -+ -+Annot* ScreenAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc) -+{ -+ return nullptr; // Not implemented -+} -+ -+ScreenAnnotation::ScreenAnnotation() -+ : Annotation( *new ScreenAnnotationPrivate() ) -+{ -+} -+ -+ScreenAnnotation::~ScreenAnnotation() -+{ -+} -+ -+void ScreenAnnotation::store( QDomNode & node, QDomDocument & document ) const -+{ -+ // store base annotation properties -+ storeBaseAnnotationProperties( node, document ); -+ -+ // create [screen] element -+ QDomElement screenElement = document.createElement( "screen" ); -+ node.appendChild( screenElement ); -+} -+ -+Annotation::SubType ScreenAnnotation::subType() const -+{ -+ return AScreen; -+} -+ -+LinkRendition* ScreenAnnotation::action() const -+{ -+ Q_D( const ScreenAnnotation ); -+ return d->action; -+} -+ -+void ScreenAnnotation::setAction( LinkRendition *action ) -+{ -+ Q_D( ScreenAnnotation ); -+ d->action = action; -+} -+ -+QString ScreenAnnotation::screenTitle() const -+{ -+ Q_D( const ScreenAnnotation ); -+ return d->title; -+} -+ -+void ScreenAnnotation::setScreenTitle( const QString &title ) -+{ -+ Q_D( ScreenAnnotation ); -+ d->title = title; -+} -+ -+Link* ScreenAnnotation::additionalAction( AdditionalActionType type ) const -+{ -+ Q_D( const ScreenAnnotation ); -+ return d->additionalAction( type ); -+} -+ -+/** WidgetAnnotation [Annotation] */ -+class WidgetAnnotationPrivate : public AnnotationPrivate -+{ -+ public: -+ Annotation * makeAlias(); -+ Annot* createNativeAnnot(::Page *destPage, DocumentData *doc); -+}; -+ -+Annotation * WidgetAnnotationPrivate::makeAlias() -+{ -+ return new WidgetAnnotation(*this); -+} -+ -+Annot* WidgetAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc) -+{ -+ return nullptr; // Not implemented -+} -+ -+WidgetAnnotation::WidgetAnnotation(WidgetAnnotationPrivate &dd) -+ : Annotation( dd ) -+{} -+ -+WidgetAnnotation::WidgetAnnotation() -+ : Annotation( *new WidgetAnnotationPrivate() ) -+{ -+} -+ -+WidgetAnnotation::~WidgetAnnotation() -+{ -+} -+ -+void WidgetAnnotation::store( QDomNode & node, QDomDocument & document ) const -+{ -+ // store base annotation properties -+ storeBaseAnnotationProperties( node, document ); -+ -+ // create [widget] element -+ QDomElement widgetElement = document.createElement( "widget" ); -+ node.appendChild( widgetElement ); -+} -+ -+Annotation::SubType WidgetAnnotation::subType() const -+{ -+ return AWidget; -+} -+ -+Link* WidgetAnnotation::additionalAction( AdditionalActionType type ) const -+{ -+ Q_D( const WidgetAnnotation ); -+ return d->additionalAction( type ); -+} -+ -+/** RichMediaAnnotation [Annotation] */ -+class RichMediaAnnotation::Params::Private -+{ -+ public: -+ Private() {} -+ -+ QString flashVars; -+}; -+ -+RichMediaAnnotation::Params::Params() -+ : d( new Private ) -+{ -+} -+ -+RichMediaAnnotation::Params::~Params() -+{ -+} -+ -+void RichMediaAnnotation::Params::setFlashVars( const QString &flashVars ) -+{ -+ d->flashVars = flashVars; -+} -+ -+QString RichMediaAnnotation::Params::flashVars() const -+{ -+ return d->flashVars; -+} -+ -+ -+class RichMediaAnnotation::Instance::Private -+{ -+ public: -+ Private() -+ : params( nullptr ) -+ { -+ } -+ -+ ~Private() -+ { -+ delete params; -+ } -+ -+ RichMediaAnnotation::Instance::Type type; -+ RichMediaAnnotation::Params *params; -+}; -+ -+RichMediaAnnotation::Instance::Instance() -+ : d( new Private ) -+{ -+} -+ -+RichMediaAnnotation::Instance::~Instance() -+{ -+} -+ -+void RichMediaAnnotation::Instance::setType( Type type ) -+{ -+ d->type = type; -+} -+ -+RichMediaAnnotation::Instance::Type RichMediaAnnotation::Instance::type() const -+{ -+ return d->type; -+} -+ -+void RichMediaAnnotation::Instance::setParams( RichMediaAnnotation::Params *params ) -+{ -+ delete d->params; -+ d->params = params; -+} -+ -+RichMediaAnnotation::Params* RichMediaAnnotation::Instance::params() const -+{ -+ return d->params; -+} -+ -+ -+class RichMediaAnnotation::Configuration::Private -+{ -+ public: -+ Private() {} -+ ~Private() -+ { -+ qDeleteAll( instances ); -+ instances.clear(); -+ } -+ -+ RichMediaAnnotation::Configuration::Type type; -+ QString name; -+ QList< RichMediaAnnotation::Instance* > instances; -+}; -+ -+RichMediaAnnotation::Configuration::Configuration() -+ : d( new Private ) -+{ -+} -+ -+RichMediaAnnotation::Configuration::~Configuration() -+{ -+} -+ -+void RichMediaAnnotation::Configuration::setType( Type type ) -+{ -+ d->type = type; -+} -+ -+RichMediaAnnotation::Configuration::Type RichMediaAnnotation::Configuration::type() const -+{ -+ return d->type; -+} -+ -+void RichMediaAnnotation::Configuration::setName( const QString &name ) -+{ -+ d->name = name; -+} -+ -+QString RichMediaAnnotation::Configuration::name() const -+{ -+ return d->name; -+} -+ -+void RichMediaAnnotation::Configuration::setInstances( const QList< RichMediaAnnotation::Instance* > &instances ) -+{ -+ qDeleteAll( d->instances ); -+ d->instances.clear(); -+ -+ d->instances = instances; -+} -+ -+QList< RichMediaAnnotation::Instance* > RichMediaAnnotation::Configuration::instances() const -+{ -+ return d->instances; -+} -+ -+ -+class RichMediaAnnotation::Asset::Private -+{ -+ public: -+ Private() -+ : embeddedFile( nullptr ) -+ { -+ } -+ -+ ~Private() -+ { -+ delete embeddedFile; -+ } -+ -+ QString name; -+ EmbeddedFile *embeddedFile; -+}; -+ -+RichMediaAnnotation::Asset::Asset() -+ : d( new Private ) -+{ -+} -+ -+RichMediaAnnotation::Asset::~Asset() -+{ -+} -+ -+void RichMediaAnnotation::Asset::setName( const QString &name ) -+{ -+ d->name = name; -+} -+ -+QString RichMediaAnnotation::Asset::name() const -+{ -+ return d->name; -+} -+ -+void RichMediaAnnotation::Asset::setEmbeddedFile( EmbeddedFile * embeddedFile ) -+{ -+ delete d->embeddedFile; -+ d->embeddedFile = embeddedFile; -+} -+ -+EmbeddedFile* RichMediaAnnotation::Asset::embeddedFile() const -+{ -+ return d->embeddedFile; -+} -+ -+ -+class RichMediaAnnotation::Content::Private -+{ -+ public: -+ Private() {} -+ ~Private() -+ { -+ qDeleteAll( configurations ); -+ configurations.clear(); -+ -+ qDeleteAll( assets ); -+ assets.clear(); -+ } -+ -+ QList< RichMediaAnnotation::Configuration* > configurations; -+ QList< RichMediaAnnotation::Asset* > assets; -+}; -+ -+RichMediaAnnotation::Content::Content() -+ : d( new Private ) -+{ -+} -+ -+RichMediaAnnotation::Content::~Content() -+{ -+} -+ -+void RichMediaAnnotation::Content::setConfigurations( const QList< RichMediaAnnotation::Configuration* > &configurations ) -+{ -+ qDeleteAll( d->configurations ); -+ d->configurations.clear(); -+ -+ d->configurations = configurations; -+} -+ -+QList< RichMediaAnnotation::Configuration* > RichMediaAnnotation::Content::configurations() const -+{ -+ return d->configurations; -+} -+ -+void RichMediaAnnotation::Content::setAssets( const QList< RichMediaAnnotation::Asset* > &assets ) -+{ -+ qDeleteAll( d->assets ); -+ d->assets.clear(); -+ -+ d->assets = assets; -+} -+ -+QList< RichMediaAnnotation::Asset* > RichMediaAnnotation::Content::assets() const -+{ -+ return d->assets; -+} -+ -+ -+class RichMediaAnnotation::Activation::Private -+{ -+ public: -+ Private() -+ : condition( RichMediaAnnotation::Activation::UserAction ) -+ { -+ } -+ -+ RichMediaAnnotation::Activation::Condition condition; -+}; -+ -+RichMediaAnnotation::Activation::Activation() -+ : d( new Private ) -+{ -+} -+ -+RichMediaAnnotation::Activation::~Activation() -+{ -+} -+ -+void RichMediaAnnotation::Activation::setCondition( Condition condition ) -+{ -+ d->condition = condition; -+} -+ -+RichMediaAnnotation::Activation::Condition RichMediaAnnotation::Activation::condition() const -+{ -+ return d->condition; -+} -+ -+ -+class RichMediaAnnotation::Deactivation::Private : public QSharedData -+{ -+ public: -+ Private() -+ : condition( RichMediaAnnotation::Deactivation::UserAction ) -+ { -+ } -+ -+ RichMediaAnnotation::Deactivation::Condition condition; -+}; -+ -+RichMediaAnnotation::Deactivation::Deactivation() -+ : d( new Private ) -+{ -+} -+ -+RichMediaAnnotation::Deactivation::~Deactivation() -+{ -+} -+ -+void RichMediaAnnotation::Deactivation::setCondition( Condition condition ) -+{ -+ d->condition = condition; -+} -+ -+RichMediaAnnotation::Deactivation::Condition RichMediaAnnotation::Deactivation::condition() const -+{ -+ return d->condition; -+} -+ -+ -+class RichMediaAnnotation::Settings::Private : public QSharedData -+{ -+ public: -+ Private() -+ : activation( nullptr ), deactivation( nullptr ) -+ { -+ } -+ -+ RichMediaAnnotation::Activation *activation; -+ RichMediaAnnotation::Deactivation *deactivation; -+}; -+ -+RichMediaAnnotation::Settings::Settings() -+ : d( new Private ) -+{ -+} -+ -+RichMediaAnnotation::Settings::~Settings() -+{ -+} -+ -+void RichMediaAnnotation::Settings::setActivation( RichMediaAnnotation::Activation *activation ) -+{ -+ delete d->activation; -+ d->activation = activation; -+} -+ -+RichMediaAnnotation::Activation* RichMediaAnnotation::Settings::activation() const -+{ -+ return d->activation; -+} -+ -+void RichMediaAnnotation::Settings::setDeactivation( RichMediaAnnotation::Deactivation *deactivation ) -+{ -+ delete d->deactivation; -+ d->deactivation = deactivation; -+} -+ -+RichMediaAnnotation::Deactivation* RichMediaAnnotation::Settings::deactivation() const -+{ -+ return d->deactivation; -+} -+ -+ -+class RichMediaAnnotationPrivate : public AnnotationPrivate -+{ -+ public: -+ RichMediaAnnotationPrivate() -+ : settings( nullptr ), content( nullptr ) -+ { -+ } -+ -+ ~RichMediaAnnotationPrivate() -+ { -+ delete settings; -+ delete content; -+ } -+ -+ Annotation * makeAlias() -+ { -+ return new RichMediaAnnotation( *this ); -+ } -+ -+ Annot* createNativeAnnot( ::Page *destPage, DocumentData *doc ) -+ { -+ Q_UNUSED( destPage ); -+ Q_UNUSED( doc ); -+ -+ return nullptr; -+ } -+ -+ RichMediaAnnotation::Settings *settings; -+ RichMediaAnnotation::Content *content; -+}; -+ -+RichMediaAnnotation::RichMediaAnnotation() -+ : Annotation( *new RichMediaAnnotationPrivate() ) -+{ -+} -+ -+RichMediaAnnotation::RichMediaAnnotation( RichMediaAnnotationPrivate &dd ) -+ : Annotation( dd ) -+{ -+} -+ -+RichMediaAnnotation::RichMediaAnnotation( const QDomNode & node ) -+ : Annotation( *new RichMediaAnnotationPrivate(), node ) -+{ -+ // loop through the whole children looking for a 'richMedia' element -+ QDomNode subNode = node.firstChild(); -+ while( subNode.isElement() ) -+ { -+ QDomElement e = subNode.toElement(); -+ subNode = subNode.nextSibling(); -+ if ( e.tagName() != "richMedia" ) -+ continue; -+ -+ // loading complete -+ break; -+ } -+} -+ -+RichMediaAnnotation::~RichMediaAnnotation() -+{ -+} -+ -+void RichMediaAnnotation::store( QDomNode & node, QDomDocument & document ) const -+{ -+ // store base annotation properties -+ storeBaseAnnotationProperties( node, document ); -+ -+ // create [richMedia] element -+ QDomElement richMediaElement = document.createElement( "richMedia" ); -+ node.appendChild( richMediaElement ); -+} -+ -+Annotation::SubType RichMediaAnnotation::subType() const -+{ -+ return ARichMedia; -+} -+ -+void RichMediaAnnotation::setSettings( RichMediaAnnotation::Settings *settings ) -+{ -+ Q_D( RichMediaAnnotation ); -+ -+ delete d->settings; -+ d->settings = settings; -+} -+ -+RichMediaAnnotation::Settings* RichMediaAnnotation::settings() const -+{ -+ Q_D( const RichMediaAnnotation ); -+ -+ return d->settings; -+} -+ -+void RichMediaAnnotation::setContent( RichMediaAnnotation::Content *content ) -+{ -+ Q_D( RichMediaAnnotation ); -+ -+ delete d->content; -+ d->content = content; -+} -+ -+RichMediaAnnotation::Content* RichMediaAnnotation::content() const -+{ -+ Q_D( const RichMediaAnnotation ); -+ -+ return d->content; -+} -+ -+//BEGIN utility annotation functions -+QColor convertAnnotColor( const AnnotColor *color ) -+{ -+ if ( !color ) -+ return QColor(); -+ -+ QColor newcolor; -+ const double *color_data = color->getValues(); -+ switch ( color->getSpace() ) -+ { -+ case AnnotColor::colorTransparent: // = 0, -+ newcolor = Qt::transparent; -+ break; -+ case AnnotColor::colorGray: // = 1, -+ newcolor.setRgbF( color_data[0], color_data[0], color_data[0] ); -+ break; -+ case AnnotColor::colorRGB: // = 3, -+ newcolor.setRgbF( color_data[0], color_data[1], color_data[2] ); -+ break; -+ case AnnotColor::colorCMYK: // = 4 -+ newcolor.setCmykF( color_data[0], color_data[1], color_data[2], color_data[3] ); -+ break; -+ } -+ return newcolor; -+} -+ -+std::unique_ptr convertQColor( const QColor &c ) -+{ -+ if ( c.alpha() == 0 ) -+ return {}; // Transparent -+ -+ switch ( c.spec() ) -+ { -+ case QColor::Rgb: -+ case QColor::Hsl: -+ case QColor::Hsv: -+ return std::make_unique( c.redF(), c.greenF(), c.blueF() ); -+ case QColor::Cmyk: -+ return std::make_unique( c.cyanF(), c.magentaF(), c.yellowF(), c.blackF() ); -+ case QColor::Invalid: -+ default: -+ return {}; -+ } -+} -+//END utility annotation functions -+ -+} -diff --git a/qt4/src/poppler-annotation.h b/qt4/src/poppler-annotation.h -new file mode 100644 -index 00000000..ac77c421 ---- /dev/null -+++ b/qt4/src/poppler-annotation.h -@@ -0,0 +1,1379 @@ -+/* poppler-annotation.h: qt interface to poppler -+ * Copyright (C) 2006-2008, 2012 Albert Astals Cid -+ * Copyright (C) 2006, 2008 Pino Toscano -+ * Copyright (C) 2007, Brad Hards -+ * Copyright (C) 2010, Philip Lorenz -+ * Copyright (C) 2012, 2015, Tobias Koenig -+ * Copyright (C) 2012, Guillermo A. Amaral B. -+ * Copyright (C) 2012, 2013 Fabio D'Urso -+ * Adapting code from -+ * Copyright (C) 2004 by Enrico Ros -+ * -+ * 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_ANNOTATION_H_ -+#define _POPPLER_ANNOTATION_H_ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "poppler-export.h" -+ -+namespace Poppler { -+ -+class Annotation; -+class AnnotationPrivate; -+class TextAnnotationPrivate; -+class LineAnnotationPrivate; -+class GeomAnnotationPrivate; -+class HighlightAnnotationPrivate; -+class StampAnnotationPrivate; -+class InkAnnotationPrivate; -+class LinkAnnotationPrivate; -+class CaretAnnotationPrivate; -+class FileAttachmentAnnotationPrivate; -+class SoundAnnotationPrivate; -+class MovieAnnotationPrivate; -+class ScreenAnnotationPrivate; -+class WidgetAnnotationPrivate; -+class RichMediaAnnotationPrivate; -+class EmbeddedFile; -+class Link; -+class SoundObject; -+class MovieObject; -+class LinkRendition; -+class Page; -+ -+/** -+ * \short Helper class for (recursive) Annotation retrieval/storage. -+ * -+ */ -+class POPPLER_QT4_EXPORT AnnotationUtils -+{ -+ public: -+ /** -+ * Restore an Annotation (with revisions if needed) from the DOM -+ * element \p annElement. -+ * \returns a pointer to the complete Annotation or 0 if element is -+ * invalid. -+ */ -+ static Annotation * createAnnotation( const QDomElement & annElement ); -+ -+ /** -+ * Save the Annotation \p ann as a child of \p annElement taking -+ * care of saving all revisions if \p ann has any. -+ */ -+ static void storeAnnotation( const Annotation * ann, -+ QDomElement & annElement, QDomDocument & document ); -+ -+ /** -+ * Returns an element called \p name from the direct children of -+ * \p parentNode or a null element if not found. -+ */ -+ static QDomElement findChildElement( const QDomNode & parentNode, -+ const QString & name ); -+}; -+ -+ -+/** -+ * \short Annotation class holding properties shared by all annotations. -+ * -+ * An Annotation is an object (text note, highlight, sound, popup window, ..) -+ * contained by a Page in the document. -+ * -+ * \warning Different Annotation objects might point to the same annotation. -+ * -+ * \section annotCreation How to add annotations -+ * -+ * Create an Annotation object of the desired subclass (for example -+ * TextAnnotation) and set its properties: -+ * @code -+ * Poppler::TextAnnotation* myann = new Poppler::TextAnnotation(Poppler::TextAnnotation::InPlace); -+ * myann->setBoundary(QRectF(0.1, 0.1, 0.2, 0.2)); // normalized coordinates: (0,0) is top-left, (1,1) is bottom-right -+ * myann->setContents("Hello, world!"); -+ * @endcode -+ * \note Always set a boundary rectangle, or nothing will be shown! -+ * -+ * Obtain a pointer to the Page where you want to add the annotation (refer to -+ * \ref req for instructions) and add the annotation: -+ * @code -+ * Poppler::Page* mypage = ...; -+ * mypage->addAnnotation(myann); -+ * @endcode -+ * -+ * You can keep on editing the annotation after it has been added to the page: -+ * @code -+ * myann->setContents("World, hello!"); // Let's change text... -+ * myann->setAuthor("Your name here"); // ...and set an author too -+ * @endcode -+ * -+ * When you're done with editing the annotation, you must destroy the Annotation -+ * object: -+ * @code -+ * delete myann; -+ * @endcode -+ * -+ * Use the PDFConverter class to save the modified document. -+ * -+ * \section annotFixedRotation FixedRotation flag specifics -+ * -+ * According to the PDF specification, annotations whose -+ * Annotation::FixedRotation flag is set must always be shown in their original -+ * orientation, no matter what the current rendering rotation or the page's -+ * Page::orientation() values are. In comparison with regular annotations, such -+ * annotations should therefore be transformed by an extra rotation at rendering -+ * time to "undo" such context-related rotations, which is equal to -+ * -(rendering_rotation + page_orientation). The rotation pivot -+ * is the top-left corner of the boundary rectangle. -+ * -+ * In practice, %Poppler's \ref Page::renderToImage only "unrotates" the -+ * page orientation, and does not unrotate the rendering rotation. -+ * This ensures consistent renderings at different Page::Rotation values: -+ * annotations are always positioned as if they were being positioned at the -+ * default page orientation. -+ * -+ * Just like regular annotations, %Poppler Qt4 exposes normalized coordinates -+ * relative to the page's default orientation. However, behind the scenes, the -+ * coordinate system is different and %Poppler transparently transforms each -+ * shape. If you never call either Annotation::setFlags or -+ * Annotation::setBoundary, you don't need to worry about this; but if you do -+ * call them, then you need to adhere to the following rules: -+ * - Whenever you toggle the Annotation::FixedRotation flag, you must -+ * set again the boundary rectangle first, and then you must set -+ * again any other geometry-related property. -+ * - Whenever you modify the boundary rectangle of an annotation whose -+ * Annotation::FixedRotation flag is set, you must set again any other -+ * geometry-related property. -+ * -+ * These two rules are necessary to make %Poppler's transparent coordinate -+ * conversion work properly. -+ */ -+class POPPLER_QT4_EXPORT Annotation -+{ -+ friend class AnnotationUtils; -+ friend class LinkMovie; -+ friend class LinkRendition; -+ -+ public: -+ // enum definitions -+ /** -+ * Annotation subclasses -+ * -+ * \sa subType() -+ */ -+ // WARNING!!! oKular uses that very same values so if you change them notify the author! -+ enum SubType -+ { -+ AText = 1, ///< TextAnnotation -+ ALine = 2, ///< LineAnnotation -+ AGeom = 3, ///< GeomAnnotation -+ AHighlight = 4, ///< HighlightAnnotation -+ AStamp = 5, ///< StampAnnotation -+ AInk = 6, ///< InkAnnotation -+ ALink = 7, ///< LinkAnnotation -+ ACaret = 8, ///< CaretAnnotation -+ AFileAttachment = 9, ///< FileAttachmentAnnotation -+ ASound = 10, ///< SoundAnnotation -+ AMovie = 11, ///< MovieAnnotation -+ AScreen = 12, ///< ScreenAnnotation \since 0.20 -+ AWidget = 13, ///< WidgetAnnotation \since 0.22 -+ ARichMedia = 14, ///< RichMediaAnnotation \since 0.36 -+ A_BASE = 0 -+ }; -+ -+ /** -+ * Annotation flags -+ * -+ * They can be OR'd together (e.g. Annotation::FixedRotation | Annotation::DenyPrint). -+ * -+ * \sa flags(), setFlags(int) -+ */ -+ // NOTE: Only flags that are known to work are documented -+ enum Flag -+ { -+ Hidden = 1, ///< Do not display or print the annotation -+ FixedSize = 2, -+ FixedRotation = 4, ///< Do not rotate the annotation according to page orientation and rendering rotation \warning Extra care is needed with this flag: see \ref annotFixedRotation -+ DenyPrint = 8, ///< Do not print the annotation -+ DenyWrite = 16, -+ DenyDelete = 32, -+ ToggleHidingOnMouse = 64, -+ External = 128 -+ }; -+ -+ enum LineStyle { Solid = 1, Dashed = 2, Beveled = 4, Inset = 8, Underline = 16 }; -+ enum LineEffect { NoEffect = 1, Cloudy = 2}; -+ enum RevScope { Root = 0 /** \since 0.20 */, Reply = 1, Group = 2, Delete = 4 }; -+ enum RevType { None = 1, Marked = 2, Unmarked = 4, Accepted = 8, Rejected = 16, Cancelled = 32, Completed = 64 }; -+ -+ /** -+ * Returns the author of the annotation. -+ */ -+ QString author() const; -+ /** -+ * Sets a new author for the annotation. -+ */ -+ void setAuthor( const QString &author ); -+ -+ QString contents() const; -+ void setContents( const QString &contents ); -+ -+ /** -+ * Returns the unique name (ID) of the annotation. -+ */ -+ QString uniqueName() const; -+ /** -+ * Sets a new unique name for the annotation. -+ * -+ * \note no check of the new uniqueName is done -+ */ -+ void setUniqueName( const QString &uniqueName ); -+ -+ QDateTime modificationDate() const; -+ void setModificationDate( const QDateTime &date ); -+ -+ QDateTime creationDate() const; -+ void setCreationDate( const QDateTime &date ); -+ -+ /** -+ * Returns this annotation's flags -+ * -+ * \sa Flag, setFlags(int) -+ */ -+ int flags() const; -+ /** -+ * Sets this annotation's flags -+ * -+ * \sa Flag, flags(), \ref annotFixedRotation -+ */ -+ void setFlags( int flags ); -+ -+ /** -+ * Returns this annotation's boundary rectangle in normalized coordinates -+ * -+ * \sa setBoundary(const QRectF&) -+ */ -+ QRectF boundary() const; -+ /** -+ * Sets this annotation's boundary rectangle -+ * -+ * The boundary rectangle is the smallest rectangle that contains the -+ * annotation. -+ * -+ * \warning This property is mandatory: you must always set this. -+ * -+ * \sa boundary(), \ref annotFixedRotation -+ */ -+ void setBoundary( const QRectF &boundary ); -+ -+ /** -+ * \short Container class for Annotation style information -+ * -+ * \since 0.20 -+ */ -+ class POPPLER_QT4_EXPORT Style -+ { -+ public: -+ Style(); -+ Style( const Style &other ); -+ Style& operator=( const Style &other ); -+ ~Style(); -+ -+ // appearance properties -+ QColor color() const; // black -+ void setColor(const QColor &color); -+ double opacity() const; // 1.0 -+ void setOpacity(double opacity); -+ -+ // pen properties -+ double width() const; // 1.0 -+ void setWidth(double width); -+ LineStyle lineStyle() const; // LineStyle::Solid -+ void setLineStyle(LineStyle style); -+ double xCorners() const; // 0.0 -+ void setXCorners(double radius); -+ double yCorners() const; // 0.0 -+ void setYCorners(double radius); -+ const QVector& dashArray() const; // [ 3 ] -+ void setDashArray(const QVector &array); -+ -+ // pen effects -+ LineEffect lineEffect() const; // LineEffect::NoEffect -+ void setLineEffect(LineEffect effect); -+ double effectIntensity() const; // 1.0 -+ void setEffectIntensity(double intens); -+ -+ private: -+ class Private; -+ QSharedDataPointer d; -+ }; -+ -+ /// \since 0.20 -+ Style style() const; -+ /// \since 0.20 -+ void setStyle( const Style& style ); -+ -+ /** -+ * \short Container class for Annotation pop-up window information -+ * -+ * \since 0.20 -+ */ -+ class POPPLER_QT4_EXPORT Popup -+ { -+ public: -+ Popup(); -+ Popup( const Popup &other ); -+ Popup& operator=( const Popup &other ); -+ ~Popup(); -+ -+ // window state (Hidden, FixedRotation, Deny* flags allowed) -+ int flags() const; // -1 (never initialized) -> 0 (if inited and shown) -+ void setFlags( int flags ); -+ -+ // geometric properties -+ QRectF geometry() const; // no default -+ void setGeometry( const QRectF &geom ); -+ -+ // window contens/override properties -+ QString title() const; // '' text in the titlebar (overrides author) -+ void setTitle( const QString &title ); -+ QString summary() const; // '' short description (displayed if not empty) -+ void setSummary( const QString &summary ); -+ QString text() const; // '' text for the window (overrides annot->contents) -+ void setText( const QString &text ); -+ -+ private: -+ class Private; -+ QSharedDataPointer d; -+ }; -+ -+ /// \since 0.20 -+ Popup popup() const; -+ /// \warning Currently does nothing \since 0.20 -+ void setPopup( const Popup& popup ); -+ -+ /// \cond PRIVATE -+ // This field is deprecated and not used any more. Use popup -+ Q_DECL_DEPRECATED struct { int width, height; } window; // Always set to zero -+ /// \endcond -+ -+ /// \since 0.20 -+ RevScope revisionScope() const; // Root -+ -+ /// \since 0.20 -+ RevType revisionType() const; // None -+ -+ /** -+ * Returns the revisions of this annotation -+ * -+ * \note The caller owns the returned annotations and they should -+ * be deleted when no longer required. -+ * -+ * \since 0.20 -+ */ -+ QList revisions() const; -+ -+ /** -+ * The type of the annotation. -+ */ -+ virtual SubType subType() const = 0; -+ -+ /** -+ * Destructor. -+ */ -+ virtual ~Annotation(); -+ -+ /** -+ * Describes the flags from an annotations 'AA' dictionary. -+ * -+ * This flag is used by the additionalAction() method for ScreenAnnotation -+ * and WidgetAnnotation. -+ * -+ * \since 0.22 -+ */ -+ enum AdditionalActionType -+ { -+ CursorEnteringAction, ///< Performed when the cursor enters the annotation's active area -+ CursorLeavingAction, ///< Performed when the cursor exists the annotation's active area -+ MousePressedAction, ///< Performed when the mouse button is pressed inside the annotation's active area -+ MouseReleasedAction, ///< Performed when the mouse button is released inside the annotation's active area -+ FocusInAction, ///< Performed when the annotation receives the input focus -+ FocusOutAction, ///< Performed when the annotation loses the input focus -+ PageOpeningAction, ///< Performed when the page containing the annotation is opened -+ PageClosingAction, ///< Performed when the page containing the annotation is closed -+ PageVisibleAction, ///< Performed when the page containing the annotation becomes visible -+ PageInvisibleAction ///< Performed when the page containing the annotation becomes invisible -+ }; -+ -+ protected: -+ /// \cond PRIVATE -+ Annotation( AnnotationPrivate &dd ); -+ Annotation( AnnotationPrivate &dd, const QDomNode &description ); -+ void storeBaseAnnotationProperties( QDomNode & parentNode, QDomDocument & document ) const; -+ Q_DECLARE_PRIVATE( Annotation ) -+ QExplicitlySharedDataPointer d_ptr; -+ /// \endcond -+ -+ private: -+ virtual void store( QDomNode & parentNode, QDomDocument & document ) const = 0; -+ Q_DISABLE_COPY( Annotation ) -+}; -+ -+/** -+ * \short Annotation containing text. -+ * -+ * A text annotation is an object showing some text directly on the page, or -+ * linked to the contents using an icon shown on a page. -+ */ -+class POPPLER_QT4_EXPORT TextAnnotation : public Annotation -+{ -+ friend class AnnotationUtils; -+ friend class AnnotationPrivate; -+ -+ public: -+ // local enums -+ enum TextType { Linked, InPlace }; -+ enum InplaceIntent { Unknown, Callout, TypeWriter }; -+ -+ TextAnnotation( TextType type ); -+ ~TextAnnotation(); -+ SubType subType() const override; -+ -+ /** -+ The type of text annotation represented by this object -+ */ -+ TextType textType() const; -+ -+ /** -+ The name of the icon for this text annotation. -+ -+ Standard names for text annotation icons are: -+ - Comment -+ - Help -+ - Insert -+ - Key -+ - NewParagraph -+ - Note (this is the default icon to use) -+ - Paragraph -+ */ -+ QString textIcon() const; -+ -+ /** -+ Set the name of the icon to use for this text annotation. -+ -+ \sa textIcon for the list of standard names -+ */ -+ void setTextIcon( const QString &icon ); -+ -+ QFont textFont() const; -+ void setTextFont( const QFont &font ); -+ /// \since 0.69 -+ QColor textColor() const; -+ /// \since 0.69 -+ void setTextColor( const QColor &color ); -+ -+ int inplaceAlign() const; -+ void setInplaceAlign( int align ); -+ -+ /** -+ Synonym for contents() -+ -+ \deprecated Use contents() instead -+ */ -+ QString inplaceText() const; -+ /** -+ Synonym for setContents() -+ -+ \deprecated Use setContents() instead -+ */ -+ void setInplaceText( const QString &text ); -+ -+ QPointF calloutPoint( int id ) const; -+ /// \since 0.20 -+ QVector calloutPoints() const; -+ /// \since 0.20 -+ void setCalloutPoints( const QVector &points ); -+ -+ InplaceIntent inplaceIntent() const; -+ void setInplaceIntent( InplaceIntent intent ); -+ -+ private: -+ TextAnnotation( const QDomNode &node ); -+ TextAnnotation( TextAnnotationPrivate &dd ); -+ virtual void store( QDomNode &parentNode, QDomDocument &document ) const; -+ void setTextType( TextType type ); -+ Q_DECLARE_PRIVATE( TextAnnotation ) -+ Q_DISABLE_COPY( TextAnnotation ) -+}; -+ -+/** -+ * \short Polygon/polyline annotation. -+ * -+ * This annotation represents a polygon (or polyline) to be drawn on a page. -+ */ -+class POPPLER_QT4_EXPORT LineAnnotation : public Annotation -+{ -+ friend class AnnotationUtils; -+ friend class AnnotationPrivate; -+ -+ public: -+ // local enums -+ /// \since 0.20 -+ enum LineType { StraightLine, Polyline }; -+ enum TermStyle { Square, Circle, Diamond, OpenArrow, ClosedArrow, None, -+ Butt, ROpenArrow, RClosedArrow, Slash }; -+ enum LineIntent { Unknown, Arrow, Dimension, PolygonCloud }; -+ -+ /// \since 0.20 -+ LineAnnotation( LineType type ); -+ ~LineAnnotation(); -+ SubType subType() const override; -+ -+ /// \since 0.20 -+ LineType lineType() const; -+ -+ QLinkedList linePoints() const; -+ void setLinePoints( const QLinkedList &points ); -+ -+ TermStyle lineStartStyle() const; -+ void setLineStartStyle( TermStyle style ); -+ -+ TermStyle lineEndStyle() const; -+ void setLineEndStyle( TermStyle style ); -+ -+ bool isLineClosed() const; -+ void setLineClosed( bool closed ); -+ -+ QColor lineInnerColor() const; -+ void setLineInnerColor( const QColor &color ); -+ -+ double lineLeadingForwardPoint() const; -+ void setLineLeadingForwardPoint( double point ); -+ -+ double lineLeadingBackPoint() const; -+ void setLineLeadingBackPoint( double point ); -+ -+ bool lineShowCaption() const; -+ void setLineShowCaption( bool show ); -+ -+ LineIntent lineIntent() const; -+ void setLineIntent( LineIntent intent ); -+ -+ private: -+ LineAnnotation( const QDomNode &node ); -+ LineAnnotation( LineAnnotationPrivate &dd ); -+ virtual void store( QDomNode &parentNode, QDomDocument &document ) const; -+ void setLineType( LineType type ); -+ Q_DECLARE_PRIVATE( LineAnnotation ) -+ Q_DISABLE_COPY( LineAnnotation ) -+}; -+ -+/** -+ * \short Geometric annotation. -+ * -+ * The geometric annotation represents a geometric figure, like a rectangle or -+ * an ellipse. -+ */ -+class POPPLER_QT4_EXPORT GeomAnnotation : public Annotation -+{ -+ friend class AnnotationUtils; -+ friend class AnnotationPrivate; -+ -+ public: -+ GeomAnnotation(); -+ virtual ~GeomAnnotation(); -+ virtual SubType subType() const; -+ -+ // common enums -+ enum GeomType { InscribedSquare, InscribedCircle }; -+ -+ GeomType geomType() const; -+ void setGeomType( GeomType style ); -+ -+ QColor geomInnerColor() const; -+ void setGeomInnerColor( const QColor &color ); -+ -+ private: -+ GeomAnnotation( const QDomNode &node ); -+ GeomAnnotation( GeomAnnotationPrivate &dd ); -+ virtual void store( QDomNode &parentNode, QDomDocument &document ) const; -+ Q_DECLARE_PRIVATE( GeomAnnotation ) -+ Q_DISABLE_COPY( GeomAnnotation ) -+}; -+ -+/** -+ * \short Text highlight annotation. -+ * -+ * The higlight annotation represents some areas of text being "highlighted". -+ */ -+class POPPLER_QT4_EXPORT HighlightAnnotation : public Annotation -+{ -+ friend class AnnotationUtils; -+ friend class AnnotationPrivate; -+ -+ public: -+ HighlightAnnotation(); -+ virtual ~HighlightAnnotation(); -+ virtual SubType subType() const; -+ -+ /** -+ The type of highlight -+ */ -+ enum HighlightType { Highlight, ///< highlighter pen style annotation -+ Squiggly, ///< jagged or squiggly underline -+ Underline, ///< straight line underline -+ StrikeOut ///< straight line through-line -+ }; -+ -+ /** -+ Structure corresponding to a QuadPoints array. This matches a -+ quadrilateral that describes the area around a word (or set of -+ words) that are to be highlighted. -+ */ -+ struct Quad -+ { -+ QPointF points[4]; // 8 valid coords -+ bool capStart; // false (vtx 1-4) [K] -+ bool capEnd; // false (vtx 2-3) [K] -+ double feather; // 0.1 (in range 0..1) [K] -+ }; -+ -+ /** -+ The type (style) of highlighting to use for this area -+ or these areas. -+ */ -+ HighlightType highlightType() const; -+ -+ /** -+ Set the type of highlighting to use for the given area -+ or areas. -+ */ -+ void setHighlightType( HighlightType type ); -+ -+ /** -+ The list of areas to highlight. -+ */ -+ QList< Quad > highlightQuads() const; -+ -+ /** -+ Set the areas to highlight. -+ */ -+ void setHighlightQuads( const QList< Quad > &quads ); -+ -+ private: -+ HighlightAnnotation( const QDomNode &node ); -+ HighlightAnnotation( HighlightAnnotationPrivate &dd ); -+ virtual void store( QDomNode &parentNode, QDomDocument &document ) const; -+ Q_DECLARE_PRIVATE( HighlightAnnotation ) -+ Q_DISABLE_COPY( HighlightAnnotation ) -+}; -+ -+/** -+ * \short Stamp annotation. -+ * -+ * A simple annotation drawing a stamp on a page. -+ */ -+class POPPLER_QT4_EXPORT StampAnnotation : public Annotation -+{ -+ friend class AnnotationUtils; -+ friend class AnnotationPrivate; -+ -+ public: -+ StampAnnotation(); -+ virtual ~StampAnnotation(); -+ virtual SubType subType() const; -+ -+ /** -+ The name of the icon for this stamp annotation. -+ -+ Standard names for stamp annotation icons are: -+ - Approved -+ - AsIs -+ - Confidential -+ - Departmental -+ - Draft (this is the default icon type) -+ - Experimental -+ - Expired -+ - Final -+ - ForComment -+ - ForPublicRelease -+ - NotApproved -+ - NotForPublicRelease -+ - Sold -+ - TopSecret -+ */ -+ QString stampIconName() const; -+ -+ /** -+ Set the icon type for this stamp annotation. -+ -+ \sa stampIconName for the list of standard icon names -+ */ -+ void setStampIconName( const QString &name ); -+ -+ private: -+ StampAnnotation( const QDomNode &node ); -+ StampAnnotation( StampAnnotationPrivate &dd ); -+ virtual void store( QDomNode &parentNode, QDomDocument &document ) const; -+ Q_DECLARE_PRIVATE( StampAnnotation ) -+ Q_DISABLE_COPY( StampAnnotation ) -+}; -+ -+/** -+ * \short Ink Annotation. -+ * -+ * Annotation representing an ink path on a page. -+ */ -+class POPPLER_QT4_EXPORT InkAnnotation : public Annotation -+{ -+ friend class AnnotationUtils; -+ friend class AnnotationPrivate; -+ -+ public: -+ InkAnnotation(); -+ virtual ~InkAnnotation(); -+ virtual SubType subType() const; -+ -+ QList< QLinkedList > inkPaths() const; -+ void setInkPaths( const QList< QLinkedList > &paths ); -+ -+ private: -+ InkAnnotation( const QDomNode &node ); -+ virtual void store( QDomNode &parentNode, QDomDocument &document ) const; -+ InkAnnotation(InkAnnotationPrivate &dd); -+ Q_DECLARE_PRIVATE( InkAnnotation ) -+ Q_DISABLE_COPY( InkAnnotation ) -+}; -+ -+class POPPLER_QT4_EXPORT LinkAnnotation : public Annotation -+{ -+ friend class AnnotationUtils; -+ friend class AnnotationPrivate; -+ -+ public: -+ virtual ~LinkAnnotation(); -+ virtual SubType subType() const; -+ -+ // local enums -+ enum HighlightMode { None, Invert, Outline, Push }; -+ -+ /** \since 0.20 */ -+ Link* linkDestination() const; -+ void setLinkDestination( Link *link ); -+ -+ HighlightMode linkHighlightMode() const; -+ void setLinkHighlightMode( HighlightMode mode ); -+ -+ QPointF linkRegionPoint( int id ) const; -+ void setLinkRegionPoint( int id, const QPointF &point ); -+ -+ private: -+ LinkAnnotation(); -+ LinkAnnotation( const QDomNode &node ); -+ LinkAnnotation( LinkAnnotationPrivate &dd ); -+ virtual void store( QDomNode &parentNode, QDomDocument &document ) const; -+ Q_DECLARE_PRIVATE( LinkAnnotation ) -+ Q_DISABLE_COPY( LinkAnnotation ) -+}; -+ -+/** -+ * \short Caret annotation. -+ * -+ * The caret annotation represents a symbol to indicate the presence of text. -+ */ -+class POPPLER_QT4_EXPORT CaretAnnotation : public Annotation -+{ -+ friend class AnnotationUtils; -+ friend class AnnotationPrivate; -+ -+ public: -+ CaretAnnotation(); -+ virtual ~CaretAnnotation(); -+ virtual SubType subType() const; -+ -+ /** -+ * The symbols for the caret annotation. -+ */ -+ enum CaretSymbol { None, P }; -+ -+ CaretSymbol caretSymbol() const; -+ void setCaretSymbol( CaretSymbol symbol ); -+ -+ private: -+ CaretAnnotation( const QDomNode &node ); -+ CaretAnnotation( CaretAnnotationPrivate &dd ); -+ virtual void store( QDomNode &parentNode, QDomDocument &document ) const; -+ Q_DECLARE_PRIVATE( CaretAnnotation ) -+ Q_DISABLE_COPY( CaretAnnotation ) -+}; -+ -+/** -+ * \short File attachment annotation. -+ * -+ * The file attachment annotation represents a file embedded in the document. -+ * -+ * \since 0.10 -+ */ -+class POPPLER_QT4_EXPORT FileAttachmentAnnotation : public Annotation -+{ -+ friend class AnnotationPrivate; -+ -+ public: -+ virtual ~FileAttachmentAnnotation(); -+ virtual SubType subType() const; -+ -+ /** -+ * Returns the name of the icon of this annotation. -+ */ -+ QString fileIconName() const; -+ /** -+ * Sets a new name for the icon of this annotation. -+ */ -+ void setFileIconName( const QString &icon ); -+ -+ /** -+ * Returns the EmbeddedFile of this annotation. -+ */ -+ EmbeddedFile* embeddedFile() const; -+ /** -+ * Sets a new EmbeddedFile for this annotation. -+ * -+ * \note FileAttachmentAnnotation takes ownership of the object -+ */ -+ void setEmbeddedFile( EmbeddedFile *ef ); -+ -+ private: -+ FileAttachmentAnnotation(); -+ FileAttachmentAnnotation( const QDomNode &node ); -+ FileAttachmentAnnotation( FileAttachmentAnnotationPrivate &dd ); -+ virtual void store( QDomNode &parentNode, QDomDocument &document ) const; -+ Q_DECLARE_PRIVATE( FileAttachmentAnnotation ) -+ Q_DISABLE_COPY( FileAttachmentAnnotation ) -+}; -+ -+/** -+ * \short Sound annotation. -+ * -+ * The sound annotation represents a sound to be played when activated. -+ * -+ * \since 0.10 -+ */ -+class POPPLER_QT4_EXPORT SoundAnnotation : public Annotation -+{ -+ friend class AnnotationPrivate; -+ -+ public: -+ virtual ~SoundAnnotation(); -+ virtual SubType subType() const; -+ -+ /** -+ * Returns the name of the icon of this annotation. -+ */ -+ QString soundIconName() const; -+ /** -+ * Sets a new name for the icon of this annotation. -+ */ -+ void setSoundIconName( const QString &icon ); -+ -+ /** -+ * Returns the SoundObject of this annotation. -+ */ -+ SoundObject* sound() const; -+ /** -+ * Sets a new SoundObject for this annotation. -+ * -+ * \note SoundAnnotation takes ownership of the object -+ */ -+ void setSound( SoundObject *ef ); -+ -+ private: -+ SoundAnnotation(); -+ SoundAnnotation( const QDomNode &node ); -+ SoundAnnotation( SoundAnnotationPrivate &dd ); -+ virtual void store( QDomNode &parentNode, QDomDocument &document ) const; -+ Q_DECLARE_PRIVATE( SoundAnnotation ) -+ Q_DISABLE_COPY( SoundAnnotation ) -+}; -+ -+/** -+ * \short Movie annotation. -+ * -+ * The movie annotation represents a movie to be played when activated. -+ * -+ * \since 0.10 -+ */ -+class POPPLER_QT4_EXPORT MovieAnnotation : public Annotation -+{ -+ friend class AnnotationPrivate; -+ -+ public: -+ virtual ~MovieAnnotation(); -+ virtual SubType subType() const; -+ -+ /** -+ * Returns the MovieObject of this annotation. -+ */ -+ MovieObject* movie() const; -+ /** -+ * Sets a new MovieObject for this annotation. -+ * -+ * \note MovieAnnotation takes ownership of the object -+ */ -+ void setMovie( MovieObject *movie ); -+ -+ /** -+ * Returns the title of the movie of this annotation. -+ */ -+ QString movieTitle() const; -+ /** -+ * Sets a new title for the movie of this annotation. -+ */ -+ void setMovieTitle( const QString &title ); -+ -+ private: -+ MovieAnnotation(); -+ MovieAnnotation( const QDomNode &node ); -+ MovieAnnotation( MovieAnnotationPrivate &dd ); -+ virtual void store( QDomNode &parentNode, QDomDocument &document ) const; -+ Q_DECLARE_PRIVATE( MovieAnnotation ) -+ Q_DISABLE_COPY( MovieAnnotation ) -+}; -+ -+/** -+ * \short Screen annotation. -+ * -+ * The screen annotation represents a screen to be played when activated. -+ * -+ * \since 0.20 -+ */ -+class POPPLER_QT4_EXPORT ScreenAnnotation : public Annotation -+{ -+ friend class AnnotationPrivate; -+ -+ public: -+ virtual ~ScreenAnnotation(); -+ -+ virtual SubType subType() const; -+ -+ /** -+ * Returns the LinkRendition of this annotation. -+ */ -+ LinkRendition* action() const; -+ -+ /** -+ * Sets a new LinkRendition for this annotation. -+ * -+ * \note ScreenAnnotation takes ownership of the object -+ */ -+ void setAction( LinkRendition *action ); -+ -+ /** -+ * Returns the title of the screen of this annotation. -+ */ -+ QString screenTitle() const; -+ -+ /** -+ * Sets a new title for the screen of this annotation. -+ */ -+ void setScreenTitle( const QString &title ); -+ -+ /** -+ * Returns the additional action of the given @p type fo the annotation or -+ * @c 0 if no action has been defined. -+ * -+ * \since 0.22 -+ */ -+ Link* additionalAction( AdditionalActionType type ) const; -+ -+ private: -+ ScreenAnnotation(); -+ ScreenAnnotation( ScreenAnnotationPrivate &dd ); -+ virtual void store( QDomNode &parentNode, QDomDocument &document ) const; // stub -+ Q_DECLARE_PRIVATE( ScreenAnnotation ) -+ Q_DISABLE_COPY( ScreenAnnotation ) -+}; -+ -+/** -+ * \short Widget annotation. -+ * -+ * The widget annotation represents a widget (form field) on a page. -+ * -+ * \note This class is just provided for consistency of the annotation API, -+ * use the FormField classes to get all the form-related information. -+ * -+ * \since 0.22 -+ */ -+class POPPLER_QT4_EXPORT WidgetAnnotation : public Annotation -+{ -+ friend class AnnotationPrivate; -+ -+ public: -+ virtual ~WidgetAnnotation(); -+ -+ virtual SubType subType() const; -+ -+ /** -+ * Returns the additional action of the given @p type fo the annotation or -+ * @c 0 if no action has been defined. -+ * -+ * \since 0.22 -+ */ -+ Link* additionalAction( AdditionalActionType type ) const; -+ -+ private: -+ WidgetAnnotation(); -+ WidgetAnnotation( WidgetAnnotationPrivate &dd ); -+ virtual void store( QDomNode &parentNode, QDomDocument &document ) const; // stub -+ Q_DECLARE_PRIVATE( WidgetAnnotation ) -+ Q_DISABLE_COPY( WidgetAnnotation ) -+}; -+ -+/** -+ * \short RichMedia annotation. -+ * -+ * The RichMedia annotation represents a video or sound on a page. -+ * -+ * \since 0.36 -+ */ -+class POPPLER_QT4_EXPORT RichMediaAnnotation : public Annotation -+{ -+ friend class AnnotationPrivate; -+ -+ public: -+ virtual ~RichMediaAnnotation(); -+ -+ virtual SubType subType() const; -+ -+ /** -+ * The params object of a RichMediaAnnotation::Instance object. -+ * -+ * The params object provides media specific parameters, to play -+ * back the media inside the PDF viewer. -+ * -+ * At the moment only parameters for flash player are supported. -+ */ -+ class POPPLER_QT4_EXPORT Params -+ { -+ friend class AnnotationPrivate; -+ -+ public: -+ Params(); -+ ~Params(); -+ -+ /** -+ * Returns the parameters for the flash player. -+ */ -+ QString flashVars() const; -+ -+ private: -+ void setFlashVars( const QString &flashVars ); -+ -+ class Private; -+ QScopedPointer d; -+ }; -+ -+ /** -+ * The instance object of a RichMediaAnnotation::Configuration object. -+ * -+ * The instance object represents one media object, that should be shown -+ * on the page. It has a media type and a Params object, to define the -+ * media specific parameters. -+ */ -+ class POPPLER_QT4_EXPORT Instance -+ { -+ friend class AnnotationPrivate; -+ -+ public: -+ /** -+ * Describes the media type of the instance. -+ */ -+ enum Type -+ { -+ Type3D, ///< A 3D media file. -+ TypeFlash, ///< A Flash media file. -+ TypeSound, ///< A sound media file. -+ TypeVideo ///< A video media file. -+ }; -+ -+ Instance(); -+ ~Instance(); -+ -+ /** -+ * Returns the media type of the instance. -+ */ -+ Type type() const; -+ -+ /** -+ * Returns the params object of the instance or @c 0 if it doesn't exist. -+ */ -+ RichMediaAnnotation::Params* params() const; -+ -+ private: -+ void setType( Type type ); -+ void setParams( RichMediaAnnotation::Params *params ); -+ -+ class Private; -+ QScopedPointer d; -+ }; -+ -+ /** -+ * The configuration object of a RichMediaAnnotation::Content object. -+ * -+ * The configuration object provides access to the various Instance objects -+ * of the rich media annotation. -+ */ -+ class POPPLER_QT4_EXPORT Configuration -+ { -+ friend class AnnotationPrivate; -+ -+ public: -+ /** -+ * Describes the media type of the configuration. -+ */ -+ enum Type -+ { -+ Type3D, ///< A 3D media file. -+ TypeFlash, ///< A Flash media file. -+ TypeSound, ///< A sound media file. -+ TypeVideo ///< A video media file. -+ }; -+ -+ Configuration(); -+ ~Configuration(); -+ -+ /** -+ * Returns the media type of the configuration. -+ */ -+ Type type() const; -+ -+ /** -+ * Returns the name of the configuration. -+ */ -+ QString name() const; -+ -+ /** -+ * Returns the list of Instance objects of the configuration. -+ */ -+ QList< RichMediaAnnotation::Instance* > instances() const; -+ -+ private: -+ void setType( Type type ); -+ void setName( const QString &name ); -+ void setInstances( const QList< RichMediaAnnotation::Instance* > &instances ); -+ -+ class Private; -+ QScopedPointer d; -+ }; -+ -+ /** -+ * The asset object of a RichMediaAnnotation::Content object. -+ * -+ * The asset object provides a mapping between identifier name, as -+ * used in the flash vars string of RichMediaAnnotation::Params, and the -+ * associated file spec object. -+ */ -+ class POPPLER_QT4_EXPORT Asset -+ { -+ friend class AnnotationPrivate; -+ -+ public: -+ Asset(); -+ ~Asset(); -+ -+ /** -+ * Returns the identifier name of the asset. -+ */ -+ QString name() const; -+ -+ /** -+ * Returns the embedded file the asset points to. -+ */ -+ EmbeddedFile* embeddedFile() const; -+ -+ private: -+ void setName( const QString &name ); -+ void setEmbeddedFile( EmbeddedFile *embeddedFile ); -+ -+ class Private; -+ QScopedPointer d; -+ }; -+ -+ /** -+ * The content object of a RichMediaAnnotation. -+ * -+ * The content object provides access to the list of configurations -+ * and assets of the rich media annotation. -+ */ -+ class POPPLER_QT4_EXPORT Content -+ { -+ friend class AnnotationPrivate; -+ -+ public: -+ Content(); -+ ~Content(); -+ -+ /** -+ * Returns the list of configuration objects of the content object. -+ */ -+ QList< RichMediaAnnotation::Configuration* > configurations() const; -+ -+ /** -+ * Returns the list of asset objects of the content object. -+ */ -+ QList< RichMediaAnnotation::Asset* > assets() const; -+ -+ private: -+ void setConfigurations( const QList< RichMediaAnnotation::Configuration* > &configurations ); -+ void setAssets( const QList< RichMediaAnnotation::Asset* > &assets ); -+ -+ class Private; -+ QScopedPointer d; -+ }; -+ -+ /** -+ * The activation object of the RichMediaAnnotation::Settings object. -+ * -+ * The activation object is a wrapper around the settings for the activation -+ * state. At the moment it provides only the activation condition. -+ */ -+ class POPPLER_QT4_EXPORT Activation -+ { -+ friend class AnnotationPrivate; -+ -+ public: -+ /** -+ * Describes the condition for activating the rich media. -+ */ -+ enum Condition { -+ PageOpened, ///< Activate when page is opened. -+ PageVisible, ///< Activate when page becomes visible. -+ UserAction ///< Activate when user interacts with the annotation. -+ }; -+ -+ Activation(); -+ ~Activation(); -+ -+ /** -+ * Returns the activation condition. -+ */ -+ Condition condition() const; -+ -+ private: -+ void setCondition( Condition condition ); -+ -+ class Private; -+ QScopedPointer d; -+ }; -+ -+ /** -+ * The deactivation object of the RichMediaAnnotation::Settings object. -+ * -+ * The deactivation object is a wrapper around the settings for the deactivation -+ * state. At the moment it provides only the deactivation condition. -+ */ -+ class POPPLER_QT4_EXPORT Deactivation -+ { -+ friend class AnnotationPrivate; -+ -+ public: -+ /** -+ * Describes the condition for deactivating the rich media. -+ */ -+ enum Condition { -+ PageClosed, ///< Deactivate when page is closed. -+ PageInvisible, ///< Deactivate when page becomes invisible. -+ UserAction ///< Deactivate when user interacts with the annotation. -+ }; -+ -+ Deactivation(); -+ ~Deactivation(); -+ -+ /** -+ * Returns the deactivation condition. -+ */ -+ Condition condition() const; -+ -+ private: -+ void setCondition( Condition condition ); -+ -+ class Private; -+ QScopedPointer d; -+ }; -+ -+ /** -+ * The settings object of a RichMediaAnnotation. -+ * -+ * The settings object provides access to the configuration objects -+ * for annotation activation and deactivation. -+ */ -+ class POPPLER_QT4_EXPORT Settings -+ { -+ friend class AnnotationPrivate; -+ -+ public: -+ Settings(); -+ ~Settings(); -+ -+ /** -+ * Returns the Activation object of the settings object or @c 0 if it doesn't exist. -+ */ -+ RichMediaAnnotation::Activation* activation() const; -+ -+ /** -+ * Returns the Deactivation object of the settings object or @c 0 if it doesn't exist. -+ */ -+ RichMediaAnnotation::Deactivation* deactivation() const; -+ -+ private: -+ void setActivation( RichMediaAnnotation::Activation *activation ); -+ void setDeactivation( RichMediaAnnotation::Deactivation *deactivation ); -+ -+ class Private; -+ QScopedPointer d; -+ }; -+ -+ /** -+ * Returns the Settings object of the rich media annotation or @c 0 if it doesn't exist. -+ */ -+ RichMediaAnnotation::Settings* settings() const; -+ -+ /** -+ * Returns the Content object of the rich media annotation or @c 0 if it doesn't exist. -+ */ -+ RichMediaAnnotation::Content* content() const; -+ -+ private: -+ void setSettings( RichMediaAnnotation::Settings *settings ); -+ void setContent( RichMediaAnnotation::Content *content ); -+ -+ RichMediaAnnotation(); -+ RichMediaAnnotation( const QDomNode &node ); -+ RichMediaAnnotation( RichMediaAnnotationPrivate &dd ); -+ virtual void store( QDomNode &parentNode, QDomDocument &document ) const; -+ Q_DECLARE_PRIVATE( RichMediaAnnotation ) -+ Q_DISABLE_COPY( RichMediaAnnotation ) -+}; -+ -+} -+ -+#endif -diff --git a/qt4/src/poppler-base-converter.cc b/qt4/src/poppler-base-converter.cc -new file mode 100644 -index 00000000..11ff17ca ---- /dev/null -+++ b/qt4/src/poppler-base-converter.cc -@@ -0,0 +1,105 @@ -+/* poppler-base-converter.cc: qt interface to poppler -+ * Copyright (C) 2007, 2009, Albert Astals Cid -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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-qt4.h" -+ -+#include "poppler-converter-private.h" -+ -+#include -+ -+namespace Poppler { -+ -+BaseConverterPrivate::BaseConverterPrivate() -+ : document(0), iodev(0), ownIodev(true) -+{ -+} -+ -+BaseConverterPrivate::~BaseConverterPrivate() -+{ -+} -+ -+QIODevice* BaseConverterPrivate::openDevice() -+{ -+ if (!iodev) -+ { -+ Q_ASSERT(!outputFileName.isEmpty()); -+ QFile *f = new QFile(outputFileName); -+ iodev = f; -+ ownIodev = true; -+ } -+ Q_ASSERT(iodev); -+ if (!iodev->isOpen()) -+ { -+ if (!iodev->open(QIODevice::WriteOnly)) -+ { -+ if (ownIodev) -+ { -+ delete iodev; -+ iodev = 0; -+ } -+ else -+ { -+ return 0; -+ } -+ } -+ } -+ return iodev; -+} -+ -+void BaseConverterPrivate::closeDevice() -+{ -+ if (ownIodev) -+ { -+ iodev->close(); -+ delete iodev; -+ iodev = 0; -+ } -+} -+ -+ -+BaseConverter::BaseConverter(BaseConverterPrivate &dd) -+ : d_ptr(&dd) -+{ -+} -+ -+BaseConverter::~BaseConverter() -+{ -+ delete d_ptr; -+} -+ -+void BaseConverter::setOutputFileName(const QString &outputFileName) -+{ -+ Q_D(BaseConverter); -+ d->outputFileName = outputFileName; -+} -+ -+void BaseConverter::setOutputDevice(QIODevice *device) -+{ -+ Q_D(BaseConverter); -+ d->iodev = device; -+ d->ownIodev = false; -+} -+ -+BaseConverter::Error BaseConverter::lastError() const -+{ -+ Q_D(const BaseConverter); -+ return d->lastError; -+} -+ -+} -diff --git a/qt4/src/poppler-converter-private.h b/qt4/src/poppler-converter-private.h -new file mode 100644 -index 00000000..dc3e9437 ---- /dev/null -+++ b/qt4/src/poppler-converter-private.h -@@ -0,0 +1,49 @@ -+/* poppler-converter-private.h: Qt4 interface to poppler -+ * Copyright (C) 2007, 2009, Albert Astals Cid -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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_QT4_CONVERTER_PRIVATE_H -+#define POPPLER_QT4_CONVERTER_PRIVATE_H -+ -+#include -+ -+class QIODevice; -+ -+namespace Poppler { -+ -+class DocumentData; -+ -+class BaseConverterPrivate -+{ -+ public: -+ BaseConverterPrivate(); -+ virtual ~BaseConverterPrivate(); -+ -+ QIODevice* openDevice(); -+ void closeDevice(); -+ -+ DocumentData *document; -+ QString outputFileName; -+ QIODevice *iodev; -+ bool ownIodev : 1; -+ BaseConverter::Error lastError; -+}; -+ -+} -+ -+#endif -diff --git a/qt4/src/poppler-document.cc b/qt4/src/poppler-document.cc -new file mode 100644 -index 00000000..d6e2fbf7 ---- /dev/null -+++ b/qt4/src/poppler-document.cc -@@ -0,0 +1,850 @@ -+/* poppler-document.cc: qt interface to poppler -+ * Copyright (C) 2005, Net Integration Technologies, Inc. -+ * Copyright (C) 2005, 2008, Brad Hards -+ * Copyright (C) 2005-2010, 2012, 2013, 2015-2017, Albert Astals Cid -+ * Copyright (C) 2006-2010, Pino Toscano -+ * Copyright (C) 2010, 2011 Hib Eris -+ * Copyright (C) 2012 Koji Otani -+ * Copyright (C) 2012, 2013 Thomas Freitag -+ * Copyright (C) 2012 Fabio D'Urso -+ * Copyright (C) 2014 Adam Reichold -+ * Copyright (C) 2015 William Bader -+ * Copyright (C) 2016 Jakub Alba -+ * Copyright (C) 2017 Adrian Johnson -+ * -+ * 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-qt4.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "poppler-private.h" -+#include "poppler-page-private.h" -+ -+#if defined(USE_CMS) -+#if defined(USE_LCMS1) -+#include -+#else -+#include -+#endif -+#endif -+ -+namespace Poppler { -+ -+ int DocumentData::count = 0; -+ -+ Document *Document::load(const QString &filePath, const QByteArray &ownerPassword, -+ const QByteArray &userPassword) -+ { -+ DocumentData *doc = new DocumentData(filePath, -+ new GooString(ownerPassword.data()), -+ new GooString(userPassword.data())); -+ return DocumentData::checkDocument(doc); -+ } -+ -+ Document *Document::loadFromData(const QByteArray &fileContents, -+ const QByteArray &ownerPassword, -+ const QByteArray &userPassword) -+ { -+ // create stream -+ DocumentData *doc = new DocumentData(fileContents, -+ new GooString(ownerPassword.data()), -+ new GooString(userPassword.data())); -+ return DocumentData::checkDocument(doc); -+ } -+ -+ Document *DocumentData::checkDocument(DocumentData *doc) -+ { -+ Document *pdoc; -+ if (doc->doc->isOk() || doc->doc->getErrorCode() == errEncrypted) { -+ pdoc = new Document(doc); -+ if (doc->doc->getErrorCode() == errEncrypted) -+ pdoc->m_doc->locked = true; -+ else -+ { -+ pdoc->m_doc->locked = false; -+ pdoc->m_doc->fillMembers(); -+ } -+ return pdoc; -+ } -+ else -+ { -+ delete doc; -+ } -+ return NULL; -+ } -+ -+ Document::Document(DocumentData *dataA) -+ { -+ m_doc = dataA; -+ } -+ -+ Document::~Document() -+ { -+ delete m_doc; -+ } -+ -+ Page *Document::page(int index) const -+ { -+ Page *page = new Page(m_doc, index); -+ if (page->m_page->page == NULL) { -+ delete page; -+ return NULL; -+ } -+ -+ return page; -+ } -+ -+ bool Document::isLocked() const -+ { -+ return m_doc->locked; -+ } -+ -+ bool Document::unlock(const QByteArray &ownerPassword, -+ const QByteArray &userPassword) -+ { -+ if (m_doc->locked) { -+ /* racier then it needs to be */ -+ DocumentData *doc2; -+ if (!m_doc->fileContents.isEmpty()) -+ { -+ doc2 = new DocumentData(m_doc->fileContents, -+ new GooString(ownerPassword.data()), -+ new GooString(userPassword.data())); -+ } -+ else -+ { -+ doc2 = new DocumentData(m_doc->m_filePath, -+ new GooString(ownerPassword.data()), -+ new GooString(userPassword.data())); -+ } -+ if (!doc2->doc->isOk()) { -+ delete doc2; -+ } else { -+ delete m_doc; -+ m_doc = doc2; -+ m_doc->locked = false; -+ m_doc->fillMembers(); -+ } -+ } -+ return m_doc->locked; -+ } -+ -+ Document::PageMode Document::pageMode() const -+ { -+ switch (m_doc->doc->getCatalog()->getPageMode()) { -+ case Catalog::pageModeNone: -+ return UseNone; -+ case Catalog::pageModeOutlines: -+ return UseOutlines; -+ case Catalog::pageModeThumbs: -+ return UseThumbs; -+ case Catalog::pageModeFullScreen: -+ return FullScreen; -+ case Catalog::pageModeOC: -+ return UseOC; -+ case Catalog::pageModeAttach: -+ return UseAttach; -+ default: -+ return UseNone; -+ } -+ } -+ -+ Document::PageLayout Document::pageLayout() const -+ { -+ switch (m_doc->doc->getCatalog()->getPageLayout()) { -+ case Catalog::pageLayoutNone: -+ return NoLayout; -+ case Catalog::pageLayoutSinglePage: -+ return SinglePage; -+ case Catalog::pageLayoutOneColumn: -+ return OneColumn; -+ case Catalog::pageLayoutTwoColumnLeft: -+ return TwoColumnLeft; -+ case Catalog::pageLayoutTwoColumnRight: -+ return TwoColumnRight; -+ case Catalog::pageLayoutTwoPageLeft: -+ return TwoPageLeft; -+ case Catalog::pageLayoutTwoPageRight: -+ return TwoPageRight; -+ default: -+ return NoLayout; -+ } -+ } -+ -+ Qt::LayoutDirection Document::textDirection() const -+ { -+ if (!m_doc->doc->getCatalog()->getViewerPreferences()) -+ return Qt::LayoutDirectionAuto; -+ -+ switch (m_doc->doc->getCatalog()->getViewerPreferences()->getDirection()) { -+ case ViewerPreferences::directionL2R: -+ return Qt::LeftToRight; -+ case ViewerPreferences::directionR2L: -+ return Qt::RightToLeft; -+ default: -+ return Qt::LayoutDirectionAuto; -+ } -+ } -+ -+ int Document::numPages() const -+ { -+ return m_doc->doc->getNumPages(); -+ } -+ -+ QList Document::fonts() const -+ { -+ QList ourList; -+ FontIterator it( 0, m_doc ); -+ while ( it.hasNext() ) -+ { -+ ourList += it.next(); -+ } -+ return ourList; -+ } -+ -+ QList Document::embeddedFiles() const -+ { -+ return m_doc->m_embeddedFiles; -+ } -+ -+ bool Document::scanForFonts( int numPages, QList *fontList ) const -+ { -+ if ( !m_doc->m_fontInfoIterator ) -+ return false; -+ if ( !m_doc->m_fontInfoIterator->hasNext() ) -+ return false; -+ while ( m_doc->m_fontInfoIterator->hasNext() && numPages ) -+ { -+ (*fontList) += m_doc->m_fontInfoIterator->next(); -+ --numPages; -+ } -+ return true; -+ } -+ -+ FontIterator* Document::newFontIterator( int startPage ) const -+ { -+ return new FontIterator( startPage, m_doc ); -+ } -+ -+ QByteArray Document::fontData(const FontInfo &fi) const -+ { -+ QByteArray result; -+ if (fi.isEmbedded()) -+ { -+ XRef *xref = m_doc->doc->getXRef()->copy(); -+ -+ Object refObj(fi.m_data->embRef); -+ Object strObj = refObj.fetch(xref); -+ if (strObj.isStream()) -+ { -+ int c; -+ strObj.streamReset(); -+ while ((c = strObj.streamGetChar()) != EOF) -+ { -+ result.append((char)c); -+ } -+ strObj.streamClose(); -+ } -+ delete xref; -+ } -+ return result; -+ } -+ -+ QString Document::info( const QString & type ) const -+ { -+ if (m_doc->locked) { -+ return QString(); -+ } -+ -+ QScopedPointer goo(m_doc->doc->getDocInfoStringEntry(type.toLatin1().constData())); -+ return UnicodeParsedString(goo.data()); -+ } -+ -+ bool Document::setInfo( const QString & key, const QString & val ) -+ { -+ if (m_doc->locked) { -+ return false; -+ } -+ -+ GooString *goo = QStringToUnicodeGooString(val); -+ m_doc->doc->setDocInfoStringEntry(key.toLatin1().constData(), goo); -+ return true; -+ } -+ -+ QString Document::title() const -+ { -+ if (m_doc->locked) { -+ return QString(); -+ } -+ -+ QScopedPointer goo(m_doc->doc->getDocInfoTitle()); -+ return UnicodeParsedString(goo.data()); -+ } -+ -+ bool Document::setTitle( const QString & val ) -+ { -+ if (m_doc->locked) { -+ return false; -+ } -+ -+ m_doc->doc->setDocInfoTitle(QStringToUnicodeGooString(val)); -+ return true; -+ } -+ -+ QString Document::author() const -+ { -+ if (m_doc->locked) { -+ return QString(); -+ } -+ -+ QScopedPointer goo(m_doc->doc->getDocInfoAuthor()); -+ return UnicodeParsedString(goo.data()); -+ } -+ -+ bool Document::setAuthor( const QString & val ) -+ { -+ if (m_doc->locked) { -+ return false; -+ } -+ -+ m_doc->doc->setDocInfoAuthor(QStringToUnicodeGooString(val)); -+ return true; -+ } -+ -+ QString Document::subject() const -+ { -+ if (m_doc->locked) { -+ return QString(); -+ } -+ -+ QScopedPointer goo(m_doc->doc->getDocInfoSubject()); -+ return UnicodeParsedString(goo.data()); -+ } -+ -+ bool Document::setSubject( const QString & val ) -+ { -+ if (m_doc->locked) { -+ return false; -+ } -+ -+ m_doc->doc->setDocInfoSubject(QStringToUnicodeGooString(val)); -+ return true; -+ } -+ -+ QString Document::keywords() const -+ { -+ if (m_doc->locked) { -+ return QString(); -+ } -+ -+ QScopedPointer goo(m_doc->doc->getDocInfoKeywords()); -+ return UnicodeParsedString(goo.data()); -+ } -+ -+ bool Document::setKeywords( const QString & val ) -+ { -+ if (m_doc->locked) { -+ return false; -+ } -+ -+ m_doc->doc->setDocInfoKeywords(QStringToUnicodeGooString(val)); -+ return true; -+ } -+ -+ QString Document::creator() const -+ { -+ if (m_doc->locked) { -+ return QString(); -+ } -+ -+ QScopedPointer goo(m_doc->doc->getDocInfoCreator()); -+ return UnicodeParsedString(goo.data()); -+ } -+ -+ bool Document::setCreator( const QString & val ) -+ { -+ if (m_doc->locked) { -+ return false; -+ } -+ -+ m_doc->doc->setDocInfoCreator(QStringToUnicodeGooString(val)); -+ return true; -+ } -+ -+ QString Document::producer() const -+ { -+ if (m_doc->locked) { -+ return QString(); -+ } -+ -+ QScopedPointer goo(m_doc->doc->getDocInfoProducer()); -+ return UnicodeParsedString(goo.data()); -+ } -+ -+ bool Document::setProducer( const QString & val ) -+ { -+ if (m_doc->locked) { -+ return false; -+ } -+ -+ m_doc->doc->setDocInfoProducer(QStringToUnicodeGooString(val)); -+ return true; -+ } -+ -+ bool Document::removeInfo() -+ { -+ if (m_doc->locked) { -+ return false; -+ } -+ -+ m_doc->doc->removeDocInfo(); -+ return true; -+ } -+ -+ QStringList Document::infoKeys() const -+ { -+ QStringList keys; -+ -+ if ( m_doc->locked ) -+ return QStringList(); -+ -+ QScopedPointer xref(m_doc->doc->getXRef()->copy()); -+ if (!xref) -+ return QStringList(); -+ Object info = xref->getDocInfo(); -+ if ( !info.isDict() ) -+ return QStringList(); -+ -+ Dict *infoDict = info.getDict(); -+ // somehow iterate over keys in infoDict -+ keys.reserve( infoDict->getLength() ); -+ for( int i=0; i < infoDict->getLength(); ++i ) { -+ keys.append( QString::fromAscii(infoDict->getKey(i)) ); -+ } -+ -+ return keys; -+ } -+ -+ QDateTime Document::date( const QString & type ) const -+ { -+ if (m_doc->locked) { -+ return QDateTime(); -+ } -+ -+ QScopedPointer goo(m_doc->doc->getDocInfoStringEntry(type.toLatin1().constData())); -+ QString str = UnicodeParsedString(goo.data()); -+ return Poppler::convertDate(str.toLatin1().data()); -+ } -+ -+ bool Document::setDate( const QString & key, const QDateTime & val ) -+ { -+ if (m_doc->locked) { -+ return false; -+ } -+ -+ m_doc->doc->setDocInfoStringEntry(key.toLatin1().constData(), QDateTimeToUnicodeGooString(val)); -+ return true; -+ } -+ -+ QDateTime Document::creationDate() const -+ { -+ if (m_doc->locked) { -+ return QDateTime(); -+ } -+ -+ QScopedPointer goo(m_doc->doc->getDocInfoCreatDate()); -+ QString str = UnicodeParsedString(goo.data()); -+ return Poppler::convertDate(str.toLatin1().data()); -+ } -+ -+ bool Document::setCreationDate( const QDateTime & val ) -+ { -+ if (m_doc->locked) { -+ return false; -+ } -+ -+ m_doc->doc->setDocInfoCreatDate(QDateTimeToUnicodeGooString(val)); -+ return true; -+ } -+ -+ QDateTime Document::modificationDate() const -+ { -+ if (m_doc->locked) { -+ return QDateTime(); -+ } -+ -+ QScopedPointer goo(m_doc->doc->getDocInfoModDate()); -+ QString str = UnicodeParsedString(goo.data()); -+ return Poppler::convertDate(str.toLatin1().data()); -+ } -+ -+ bool Document::setModificationDate( const QDateTime & val ) -+ { -+ if (m_doc->locked) { -+ return false; -+ } -+ -+ m_doc->doc->setDocInfoModDate(QDateTimeToUnicodeGooString(val)); -+ return true; -+ } -+ -+ bool Document::isEncrypted() const -+ { -+ return m_doc->doc->isEncrypted(); -+ } -+ -+ bool Document::isLinearized() const -+ { -+ return m_doc->doc->isLinearized(); -+ } -+ -+ bool Document::okToPrint() const -+ { -+ return m_doc->doc->okToPrint(); -+ } -+ -+ bool Document::okToPrintHighRes() const -+ { -+ return m_doc->doc->okToPrintHighRes(); -+ } -+ -+ bool Document::okToChange() const -+ { -+ return m_doc->doc->okToChange(); -+ } -+ -+ bool Document::okToCopy() const -+ { -+ return m_doc->doc->okToCopy(); -+ } -+ -+ bool Document::okToAddNotes() const -+ { -+ return m_doc->doc->okToAddNotes(); -+ } -+ -+ bool Document::okToFillForm() const -+ { -+ return m_doc->doc->okToFillForm(); -+ } -+ -+ bool Document::okToCreateFormFields() const -+ { -+ return ( okToFillForm() && okToChange() ); -+ } -+ -+ bool Document::okToExtractForAccessibility() const -+ { -+ return m_doc->doc->okToAccessibility(); -+ } -+ -+ bool Document::okToAssemble() const -+ { -+ return m_doc->doc->okToAssemble(); -+ } -+ -+ double Document::pdfVersion() const -+ { -+ return m_doc->doc->getPDFMajorVersion () + m_doc->doc->getPDFMinorVersion() / 10.0; -+ } -+ -+ void Document::getPdfVersion(int *major, int *minor) const -+ { -+ if (major) -+ *major = m_doc->doc->getPDFMajorVersion(); -+ if (minor) -+ *minor = m_doc->doc->getPDFMinorVersion(); -+ } -+ -+ Page *Document::page(const QString &label) const -+ { -+ GooString label_g(label.toAscii().data()); -+ int index; -+ -+ if (!m_doc->doc->getCatalog()->labelToIndex (&label_g, &index)) -+ return NULL; -+ -+ return page(index); -+ } -+ -+ bool Document::hasEmbeddedFiles() const -+ { -+ return (!(0 == m_doc->doc->getCatalog()->numEmbeddedFiles())); -+ } -+ -+ QDomDocument *Document::toc() const -+ { -+ Outline * outline = m_doc->doc->getOutline(); -+ if ( !outline ) -+ return NULL; -+ -+ const std::vector<::OutlineItem*> * items = outline->getItems(); -+ if ( !items || items->size() < 1 ) -+ return NULL; -+ -+ QDomDocument *toc = new QDomDocument(); -+ if ( items->size() > 0 ) -+ m_doc->addTocChildren( toc, toc, items ); -+ -+ return toc; -+ } -+ -+ LinkDestination *Document::linkDestination( const QString &name ) -+ { -+ GooString * namedDest = QStringToGooString( name ); -+ LinkDestinationData ldd(NULL, namedDest, m_doc, false); -+ LinkDestination *ld = new LinkDestination(ldd); -+ delete namedDest; -+ return ld; -+ } -+ -+ void Document::setPaperColor(const QColor &color) -+ { -+ m_doc->setPaperColor(color); -+ } -+ -+ void Document::setColorDisplayProfile(void* outputProfileA) -+ { -+#if defined(USE_CMS) -+ GfxColorSpace::setDisplayProfile((cmsHPROFILE)outputProfileA); -+#else -+ Q_UNUSED(outputProfileA); -+#endif -+ } -+ -+ void Document::setColorDisplayProfileName(const QString &name) -+ { -+#if defined(USE_CMS) -+ GooString *profileName = QStringToGooString( name ); -+ GfxColorSpace::setDisplayProfileName(profileName); -+ delete profileName; -+#else -+ Q_UNUSED(name); -+#endif -+ } -+ -+ void* Document::colorRgbProfile() const -+ { -+#if defined(USE_CMS) -+ return (void*)GfxColorSpace::getRGBProfile(); -+#else -+ return NULL; -+#endif -+ } -+ -+ void* Document::colorDisplayProfile() const -+ { -+#if defined(USE_CMS) -+ return (void*)GfxColorSpace::getDisplayProfile(); -+#else -+ return NULL; -+#endif -+ } -+ -+ QColor Document::paperColor() const -+ { -+ return m_doc->paperColor; -+ } -+ -+ void Document::setRenderBackend( Document::RenderBackend backend ) -+ { -+ // no need to delete the outputdev as for the moment we always create a splash one -+ // as the arthur one does not allow "precaching" due to it's signature -+ // delete m_doc->m_outputDev; -+ // m_doc->m_outputDev = NULL; -+ m_doc->m_backend = backend; -+ } -+ -+ Document::RenderBackend Document::renderBackend() const -+ { -+ return m_doc->m_backend; -+ } -+ -+ QSet Document::availableRenderBackends() -+ { -+ QSet ret; -+#if defined(HAVE_SPLASH) -+ ret << Document::SplashBackend; -+#endif -+ ret << Document::ArthurBackend; -+ return ret; -+ } -+ -+ void Document::setRenderHint( Document::RenderHint hint, bool on ) -+ { -+ const bool touchesOverprinting = hint & Document::OverprintPreview; -+ -+ int hintForOperation = hint; -+ if (touchesOverprinting && !isOverprintPreviewAvailable()) -+ hintForOperation = hintForOperation & ~(int)Document::OverprintPreview; -+ -+ if ( on ) -+ m_doc->m_hints |= hintForOperation; -+ else -+ m_doc->m_hints &= ~hintForOperation; -+ -+ } -+ -+ Document::RenderHints Document::renderHints() const -+ { -+ return Document::RenderHints( m_doc->m_hints ); -+ } -+ -+ PSConverter *Document::psConverter() const -+ { -+ return new PSConverter(m_doc); -+ } -+ -+ PDFConverter *Document::pdfConverter() const -+ { -+ return new PDFConverter(m_doc); -+ } -+ -+ QString Document::metadata() const -+ { -+ QString result; -+ Catalog *catalog = m_doc->doc->getCatalog(); -+ if (catalog && catalog->isOk()) -+ { -+ GooString *s = catalog->readMetadata(); -+ if (s) result = UnicodeParsedString(s); -+ delete s; -+ } -+ return result; -+ } -+ -+ bool Document::hasOptionalContent() const -+ { -+ return ( m_doc->doc->getOptContentConfig() && m_doc->doc->getOptContentConfig()->hasOCGs() ); -+ } -+ -+ OptContentModel *Document::optionalContentModel() -+ { -+ if (m_doc->m_optContentModel.isNull()) { -+ m_doc->m_optContentModel = new OptContentModel(m_doc->doc->getOptContentConfig(), 0); -+ } -+ return (OptContentModel *)m_doc->m_optContentModel; -+ } -+ -+ QStringList Document::scripts() const -+ { -+ Catalog *catalog = m_doc->doc->getCatalog(); -+ const int numScripts = catalog->numJS(); -+ QStringList scripts; -+ for (int i = 0; i < numScripts; ++i) { -+ GooString *s = catalog->getJS(i); -+ if (s) { -+ scripts.append(UnicodeParsedString(s)); -+ delete s; -+ } -+ } -+ return scripts; -+ } -+ -+ bool Document::getPdfId(QByteArray *permanentId, QByteArray *updateId) const -+ { -+ GooString gooPermanentId; -+ GooString gooUpdateId; -+ -+ if (!m_doc->doc->getID(permanentId ? &gooPermanentId : 0, updateId ? &gooUpdateId : 0)) -+ return false; -+ -+ if (permanentId) -+ *permanentId = gooPermanentId.c_str(); -+ if (updateId) -+ *updateId = gooUpdateId.c_str(); -+ -+ return true; -+ } -+ -+ Document::FormType Document::formType() const -+ { -+ switch ( m_doc->doc->getCatalog()->getFormType() ) -+ { -+ case Catalog::NoForm: -+ return Document::NoForm; -+ case Catalog::AcroForm: -+ return Document::AcroForm; -+ case Catalog::XfaForm: -+ return Document::XfaForm; -+ } -+ -+ return Document::NoForm; // make gcc happy -+ } -+ -+ QDateTime convertDate( char *dateString ) -+ { -+ int year, mon, day, hour, min, sec, tzHours, tzMins; -+ char tz; -+ -+ if ( parseDateString( dateString, &year, &mon, &day, &hour, &min, &sec, &tz, &tzHours, &tzMins ) ) -+ { -+ QDate d( year, mon, day ); -+ QTime t( hour, min, sec ); -+ if ( d.isValid() && t.isValid() ) { -+ QDateTime dt( d, t, Qt::UTC ); -+ if ( tz ) { -+ // then we have some form of timezone -+ if ( 'Z' == tz ) { -+ // We are already at UTC -+ } else if ( '+' == tz ) { -+ // local time is ahead of UTC -+ dt = dt.addSecs(-1*((tzHours*60)+tzMins)*60); -+ } else if ( '-' == tz ) { -+ // local time is behind UTC -+ dt = dt.addSecs(((tzHours*60)+tzMins)*60); -+ } else { -+ qWarning("unexpected tz val"); -+ } -+ } -+ return dt; -+ } -+ } -+ return QDateTime(); -+ } -+ -+ bool isCmsAvailable() -+ { -+#if defined(USE_CMS) -+ return true; -+#else -+ return false; -+#endif -+ } -+ -+ bool isOverprintPreviewAvailable() { -+#ifdef SPLASH_CMYK -+ return true; -+#else -+ return false; -+#endif -+ } -+ -+} -diff --git a/qt4/src/poppler-embeddedfile-private.h b/qt4/src/poppler-embeddedfile-private.h -new file mode 100644 -index 00000000..83549dad ---- /dev/null -+++ b/qt4/src/poppler-embeddedfile-private.h -@@ -0,0 +1,42 @@ -+/* poppler-embeddedfile-private.h: Qt4 interface to poppler -+ * Copyright (C) 2005, 2008, 2009, 2012, Albert Astals Cid -+ * Copyright (C) 2005, Brad Hards -+ * Copyright (C) 2008, 2011, Pino Toscano -+ * -+ * 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_EMBEDDEDFILE_PRIVATE_H -+#define POPPLER_EMBEDDEDFILE_PRIVATE_H -+ -+class FileSpec; -+ -+namespace Poppler -+{ -+ -+class EmbeddedFileData -+{ -+public: -+ EmbeddedFileData(FileSpec *fs); -+ ~EmbeddedFileData(); -+ -+ EmbFile *embFile() const; -+ -+ FileSpec *filespec; -+}; -+ -+} -+ -+#endif -diff --git a/qt4/src/poppler-embeddedfile.cc b/qt4/src/poppler-embeddedfile.cc -new file mode 100644 -index 00000000..f70573ac ---- /dev/null -+++ b/qt4/src/poppler-embeddedfile.cc -@@ -0,0 +1,135 @@ -+/* poppler-document.cc: qt interface to poppler -+ * Copyright (C) 2005, 2008, 2009, 2012, 2013, Albert Astals Cid -+ * Copyright (C) 2005, Brad Hards -+ * Copyright (C) 2008, 2011, Pino Toscano -+ * -+ * 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-qt4.h" -+ -+#include -+#include -+ -+#include "Object.h" -+#include "Stream.h" -+#include "Catalog.h" -+#include "FileSpec.h" -+ -+#include "poppler-private.h" -+#include "poppler-embeddedfile-private.h" -+ -+namespace Poppler -+{ -+ -+EmbeddedFileData::EmbeddedFileData(FileSpec *fs) -+ : filespec(fs) -+{ -+} -+ -+EmbeddedFileData::~EmbeddedFileData() -+{ -+ delete filespec; -+} -+ -+EmbFile *EmbeddedFileData::embFile() const -+{ -+ return filespec->isOk() ? filespec->getEmbeddedFile() : NULL; -+} -+ -+ -+EmbeddedFile::EmbeddedFile(EmbFile *embfile) -+ : m_embeddedFile(0) -+{ -+ assert(!"You must not use this private constructor!"); -+} -+ -+EmbeddedFile::EmbeddedFile(EmbeddedFileData &dd) -+ : m_embeddedFile(&dd) -+{ -+} -+ -+EmbeddedFile::~EmbeddedFile() -+{ -+ delete m_embeddedFile; -+} -+ -+QString EmbeddedFile::name() const -+{ -+ GooString *goo = m_embeddedFile->filespec->getFileName(); -+ return goo ? UnicodeParsedString(goo) : QString(); -+} -+ -+QString EmbeddedFile::description() const -+{ -+ GooString *goo = m_embeddedFile->filespec->getDescription(); -+ return goo ? UnicodeParsedString(goo) : QString(); -+} -+ -+int EmbeddedFile::size() const -+{ -+ return m_embeddedFile->embFile() ? m_embeddedFile->embFile()->size() : -1; -+} -+ -+QDateTime EmbeddedFile::modDate() const -+{ -+ GooString *goo = m_embeddedFile->embFile() ? m_embeddedFile->embFile()->modDate() : NULL; -+ return goo ? convertDate(goo->c_str()) : QDateTime(); -+} -+ -+QDateTime EmbeddedFile::createDate() const -+{ -+ GooString *goo = m_embeddedFile->embFile() ? m_embeddedFile->embFile()->createDate() : NULL; -+ return goo ? convertDate(goo->c_str()) : QDateTime(); -+} -+ -+QByteArray EmbeddedFile::checksum() const -+{ -+ GooString *goo = m_embeddedFile->embFile() ? m_embeddedFile->embFile()->checksum() : NULL; -+ return goo ? QByteArray::fromRawData(goo->c_str(), goo->getLength()) : QByteArray(); -+} -+ -+QString EmbeddedFile::mimeType() const -+{ -+ GooString *goo = m_embeddedFile->embFile() ? m_embeddedFile->embFile()->mimeType() : NULL; -+ return goo ? QString(goo->c_str()) : QString(); -+} -+ -+QByteArray EmbeddedFile::data() -+{ -+ if (!isValid()) -+ return QByteArray(); -+ Stream *stream = m_embeddedFile->embFile() ? m_embeddedFile->embFile()->stream() : NULL; -+ if (!stream) -+ return QByteArray(); -+ -+ stream->reset(); -+ int dataLen = 0; -+ QByteArray fileArray; -+ int i; -+ while ( (i = stream->getChar()) != EOF) { -+ fileArray[dataLen] = (char)i; -+ ++dataLen; -+ } -+ fileArray.resize(dataLen); -+ return fileArray; -+} -+ -+bool EmbeddedFile::isValid() const -+{ -+ return m_embeddedFile->filespec->isOk(); -+} -+ -+} -diff --git a/qt4/src/poppler-export.h b/qt4/src/poppler-export.h -new file mode 100644 -index 00000000..2e2f6ff8 ---- /dev/null -+++ b/qt4/src/poppler-export.h -@@ -0,0 +1,20 @@ -+/* -+* This file is used to set the poppler_qt4_EXPORT macros right. -+* This is needed for setting the visibility on windows, it will have no effect on other platforms. -+*/ -+#if defined(_WIN32) -+# define _POPPLER_QT4_LIB_EXPORT __declspec(dllexport) -+# define _POPPLER_QT4_LIB_IMPORT __declspec(dllimport) -+#elif defined(__GNUC__) -+# define _POPPLER_QT4_LIB_EXPORT __attribute__((visibility("default"))) -+# define _POPPLER_QT4_LIB_IMPORT -+#else -+# define _POPPLER_QT4_LIB_EXPORT -+# define _POPPLER_QT4_LIB_IMPORT -+#endif -+ -+#ifdef poppler_qt4_EXPORTS -+# define POPPLER_QT4_EXPORT _POPPLER_QT4_LIB_EXPORT -+#else -+# define POPPLER_QT4_EXPORT _POPPLER_QT4_LIB_IMPORT -+#endif -diff --git a/qt4/src/poppler-fontinfo.cc b/qt4/src/poppler-fontinfo.cc -new file mode 100644 -index 00000000..5bb9e3a8 ---- /dev/null -+++ b/qt4/src/poppler-fontinfo.cc -@@ -0,0 +1,150 @@ -+/* poppler-qt.h: qt interface to poppler -+ * Copyright (C) 2005, Net Integration Technologies, Inc. -+ * Copyright (C) 2005, Tobias Koening -+ * Copyright (C) 2005, Brad Hards -+ * Copyright (C) 2005-2008, 2015, Albert Astals Cid -+ * Copyright (C) 2008, 2009, Pino Toscano -+ * -+ * 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-qt4.h" -+#include "poppler-private.h" -+ -+namespace Poppler { -+ -+FontInfo::FontInfo() -+{ -+ m_data = new FontInfoData(); -+} -+ -+FontInfo::FontInfo( const FontInfoData &fid ) -+{ -+ m_data = new FontInfoData(fid); -+} -+ -+FontInfo::FontInfo( const FontInfo &fi ) -+{ -+ m_data = new FontInfoData(*fi.m_data); -+} -+ -+FontInfo::~FontInfo() -+{ -+ delete m_data; -+} -+ -+QString FontInfo::name() const -+{ -+ return m_data->fontName; -+} -+ -+QString FontInfo::file() const -+{ -+ return m_data->fontFile; -+} -+ -+bool FontInfo::isEmbedded() const -+{ -+ return m_data->isEmbedded; -+} -+ -+bool FontInfo::isSubset() const -+{ -+ return m_data->isSubset; -+} -+ -+FontInfo::Type FontInfo::type() const -+{ -+ return m_data->type; -+} -+ -+QString FontInfo::typeName() const -+{ -+ switch (type()) { -+ case unknown: -+ return QObject::tr("unknown"); -+ case Type1: -+ return QObject::tr("Type 1"); -+ case Type1C: -+ return QObject::tr("Type 1C"); -+ case Type3: -+ return QObject::tr("Type 3"); -+ case TrueType: -+ return QObject::tr("TrueType"); -+ case CIDType0: -+ return QObject::tr("CID Type 0"); -+ case CIDType0C: -+ return QObject::tr("CID Type 0C"); -+ case CIDTrueType: -+ return QObject::tr("CID TrueType"); -+ case Type1COT: -+ return QObject::tr("Type 1C (OpenType)"); -+ case TrueTypeOT: -+ return QObject::tr("TrueType (OpenType)"); -+ case CIDType0COT: -+ return QObject::tr("CID Type 0C (OpenType)"); -+ case CIDTrueTypeOT: -+ return QObject::tr("CID TrueType (OpenType)"); -+ } -+ return QObject::tr("Bug: unexpected font type. Notify poppler mailing list!"); -+} -+ -+FontInfo& FontInfo::operator=( const FontInfo &fi ) -+{ -+ if (this == &fi) -+ return *this; -+ -+ *m_data = *fi.m_data; -+ return *this; -+} -+ -+ -+FontIterator::FontIterator( int startPage, DocumentData *dd ) -+ : d( new FontIteratorData( startPage, dd ) ) -+{ -+} -+ -+FontIterator::~FontIterator() -+{ -+ delete d; -+} -+ -+QList FontIterator::next() -+{ -+ ++d->currentPage; -+ -+ QList fonts; -+ const std::vector<::FontInfo*> items = d->fontInfoScanner.scan( 1 ); -+ fonts.reserve( items.size() ); -+ for ( ::FontInfo* entry : items ) { -+ fonts.append( FontInfo( FontInfoData( entry ) ) ); -+ delete entry; -+ } -+ -+ -+ return fonts; -+} -+ -+bool FontIterator::hasNext() const -+{ -+ return ( d->currentPage + 1 ) < d->totalPages; -+} -+ -+int FontIterator::currentPage() const -+{ -+ return d->currentPage; -+} -+ -+} -diff --git a/qt4/src/poppler-form.cc b/qt4/src/poppler-form.cc -new file mode 100644 -index 00000000..57cde574 ---- /dev/null -+++ b/qt4/src/poppler-form.cc -@@ -0,0 +1,416 @@ -+/* poppler-form.h: qt4 interface to poppler -+ * Copyright (C) 2007-2008, 2011, Pino Toscano -+ * Copyright (C) 2008, 2011, 2012, 2015, 2017, Albert Astals Cid -+ * Copyright (C) 2011 Carlos Garcia Campos -+ * Copyright (C) 2012, Adam Reichold -+ * -+ * 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-qt4.h" -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "poppler-form.h" -+#include "poppler-page-private.h" -+#include "poppler-private.h" -+#include "poppler-annotation-helper.h" -+ -+#include -+ -+namespace { -+ -+Qt::Alignment formTextAlignment(::FormWidget *fm) -+{ -+ Qt::Alignment qtalign = Qt::AlignLeft; -+ switch (fm->getField()->getTextQuadding()) -+ { -+ case quaddingCentered: -+ qtalign = Qt::AlignHCenter; -+ break; -+ case quaddingRightJustified: -+ qtalign = Qt::AlignRight; -+ break; -+ case quaddingLeftJustified: -+ qtalign = Qt::AlignLeft; -+ } -+ return qtalign; -+} -+ -+} -+ -+namespace Poppler { -+ -+FormField::FormField(FormFieldData &dd) -+ : m_formData(&dd) -+{ -+ const int rotation = m_formData->page->getRotate(); -+ // reading the coords -+ double left, top, right, bottom; -+ m_formData->fm->getRect(&left, &bottom, &right, &top); -+ // build a normalized transform matrix for this page at 100% scale -+ GfxState gfxState( 72.0, 72.0, m_formData->page->getCropBox(), rotation, true ); -+ const double * gfxCTM = gfxState.getCTM(); -+ double MTX[6]; -+ double pageWidth = m_formData->page->getCropWidth(); -+ double pageHeight = m_formData->page->getCropHeight(); -+ // landscape and seascape page rotation: be sure to use the correct (== rotated) page size -+ if (((rotation / 90) % 2) == 1) -+ qSwap(pageWidth, pageHeight); -+ for ( int i = 0; i < 6; i+=2 ) -+ { -+ MTX[i] = gfxCTM[i] / pageWidth; -+ MTX[i+1] = gfxCTM[i+1] / pageHeight; -+ } -+ QPointF topLeft; -+ XPDFReader::transform( MTX, qMin( left, right ), qMax( top, bottom ), topLeft ); -+ QPointF bottomRight; -+ XPDFReader::transform( MTX, qMax( left, right ), qMin( top, bottom ), bottomRight ); -+ m_formData->box = QRectF(topLeft, QSizeF(bottomRight.x() - topLeft.x(), bottomRight.y() - topLeft.y())); -+} -+ -+FormField::~FormField() -+{ -+ delete m_formData; -+ m_formData = 0; -+} -+ -+QRectF FormField::rect() const -+{ -+ return m_formData->box; -+} -+ -+int FormField::id() const -+{ -+ return m_formData->fm->getID(); -+} -+ -+QString FormField::name() const -+{ -+ QString name; -+ if (const GooString *goo = m_formData->fm->getPartialName()) -+ { -+ name = QString::fromLatin1(goo->c_str()); -+ } -+ return name; -+} -+ -+QString FormField::fullyQualifiedName() const -+{ -+ QString name; -+ if (const GooString *goo = m_formData->fm->getFullyQualifiedName()) -+ { -+ name = UnicodeParsedString(goo); -+ } -+ return name; -+} -+ -+QString FormField::uiName() const -+{ -+ QString name; -+ if (const GooString *goo = m_formData->fm->getAlternateUiName()) -+ { -+ name = QString::fromLatin1(goo->c_str()); -+ } -+ return name; -+} -+ -+bool FormField::isReadOnly() const -+{ -+ return m_formData->fm->isReadOnly(); -+} -+ -+bool FormField::isVisible() const -+{ -+ return !(m_formData->fm->getWidgetAnnotation()->getFlags() & Annot::flagHidden); -+} -+ -+Link* FormField::activationAction() const -+{ -+ Link* action = 0; -+ if (::LinkAction *act = m_formData->fm->getActivationAction()) -+ { -+ action = PageData::convertLinkActionToLink(act, m_formData->doc, QRectF()); -+ } -+ return action; -+} -+ -+ -+FormFieldButton::FormFieldButton(DocumentData *doc, ::Page *p, ::FormWidgetButton *w) -+ : FormField(*new FormFieldData(doc, p, w)) -+{ -+} -+ -+FormFieldButton::~FormFieldButton() -+{ -+} -+ -+FormFieldButton::FormType FormFieldButton::type() const -+{ -+ return FormField::FormButton; -+} -+ -+FormFieldButton::ButtonType FormFieldButton::buttonType() const -+{ -+ FormWidgetButton* fwb = static_cast(m_formData->fm); -+ switch (fwb->getButtonType()) -+ { -+ case formButtonCheck: -+ return FormFieldButton::CheckBox; -+ break; -+ case formButtonPush: -+ return FormFieldButton::Push; -+ break; -+ case formButtonRadio: -+ return FormFieldButton::Radio; -+ break; -+ } -+ return FormFieldButton::CheckBox; -+} -+ -+QString FormFieldButton::caption() const -+{ -+ FormWidgetButton* fwb = static_cast(m_formData->fm); -+ QString ret; -+ if (fwb->getButtonType() == formButtonPush) -+ { -+ Dict *dict = m_formData->fm->getObj()->getDict(); -+ Object obj1 = dict->lookup("MK"); -+ if (obj1.isDict()) -+ { -+ AnnotAppearanceCharacs appearCharacs(obj1.getDict()); -+ if (appearCharacs.getNormalCaption()) -+ { -+ ret = UnicodeParsedString(appearCharacs.getNormalCaption()); -+ } -+ } -+ } -+ else -+ { -+ if (const char *goo = fwb->getOnStr()) -+ { -+ ret = QString::fromUtf8(goo); -+ } -+ } -+ return ret; -+} -+ -+bool FormFieldButton::state() const -+{ -+ FormWidgetButton* fwb = static_cast(m_formData->fm); -+ return fwb->getState(); -+} -+ -+void FormFieldButton::setState( bool state ) -+{ -+ FormWidgetButton* fwb = static_cast(m_formData->fm); -+ fwb->setState((bool)state); -+} -+ -+QList FormFieldButton::siblings() const -+{ -+ FormWidgetButton* fwb = static_cast(m_formData->fm); -+ ::FormFieldButton* ffb = static_cast< ::FormFieldButton* >(fwb->getField()); -+ if (fwb->getButtonType() == formButtonPush) -+ return QList(); -+ -+ QList ret; -+ for (int i = 0; i < ffb->getNumSiblings(); ++i) -+ { -+ ::FormFieldButton* sibling = static_cast< ::FormFieldButton* >(ffb->getSibling(i)); -+ for (int j = 0; j < sibling->getNumWidgets(); ++j) -+ { -+ FormWidget *w = sibling->getWidget(j); -+ if (w) ret.append(w->getID()); -+ } -+ } -+ -+ return ret; -+} -+ -+ -+FormFieldText::FormFieldText(DocumentData *doc, ::Page *p, ::FormWidgetText *w) -+ : FormField(*new FormFieldData(doc, p, w)) -+{ -+} -+ -+FormFieldText::~FormFieldText() -+{ -+} -+ -+FormField::FormType FormFieldText::type() const -+{ -+ return FormField::FormText; -+} -+ -+FormFieldText::TextType FormFieldText::textType() const -+{ -+ FormWidgetText* fwt = static_cast(m_formData->fm); -+ if (fwt->isFileSelect()) -+ return FormFieldText::FileSelect; -+ else if (fwt->isMultiline()) -+ return FormFieldText::Multiline; -+ return FormFieldText::Normal; -+} -+ -+QString FormFieldText::text() const -+{ -+ const GooString *goo = static_cast(m_formData->fm)->getContent(); -+ return UnicodeParsedString(goo); -+} -+ -+void FormFieldText::setText( const QString& text ) -+{ -+ FormWidgetText* fwt = static_cast(m_formData->fm); -+ GooString * goo = QStringToUnicodeGooString( text ); -+ fwt->setContent( goo ); -+ delete goo; -+} -+ -+bool FormFieldText::isPassword() const -+{ -+ FormWidgetText* fwt = static_cast(m_formData->fm); -+ return fwt->isPassword(); -+} -+ -+bool FormFieldText::isRichText() const -+{ -+ FormWidgetText* fwt = static_cast(m_formData->fm); -+ return fwt->isRichText(); -+} -+ -+int FormFieldText::maximumLength() const -+{ -+ FormWidgetText* fwt = static_cast(m_formData->fm); -+ const int maxlen = fwt->getMaxLen(); -+ return maxlen > 0 ? maxlen : -1; -+} -+ -+Qt::Alignment FormFieldText::textAlignment() const -+{ -+ return formTextAlignment(m_formData->fm); -+} -+ -+bool FormFieldText::canBeSpellChecked() const -+{ -+ FormWidgetText* fwt = static_cast(m_formData->fm); -+ return !fwt->noSpellCheck(); -+} -+ -+ -+FormFieldChoice::FormFieldChoice(DocumentData *doc, ::Page *p, ::FormWidgetChoice *w) -+ : FormField(*new FormFieldData(doc, p, w)) -+{ -+} -+ -+FormFieldChoice::~FormFieldChoice() -+{ -+} -+ -+FormFieldChoice::FormType FormFieldChoice::type() const -+{ -+ return FormField::FormChoice; -+} -+ -+FormFieldChoice::ChoiceType FormFieldChoice::choiceType() const -+{ -+ FormWidgetChoice* fwc = static_cast(m_formData->fm); -+ if (fwc->isCombo()) -+ return FormFieldChoice::ComboBox; -+ return FormFieldChoice::ListBox; -+} -+ -+QStringList FormFieldChoice::choices() const -+{ -+ FormWidgetChoice* fwc = static_cast(m_formData->fm); -+ QStringList ret; -+ int num = fwc->getNumChoices(); -+ ret.reserve(num); -+ for (int i = 0; i < num; ++i) -+ { -+ ret.append(UnicodeParsedString(fwc->getChoice(i))); -+ } -+ return ret; -+} -+ -+bool FormFieldChoice::isEditable() const -+{ -+ FormWidgetChoice* fwc = static_cast(m_formData->fm); -+ return fwc->isCombo() ? fwc->hasEdit() : false; -+} -+ -+bool FormFieldChoice::multiSelect() const -+{ -+ FormWidgetChoice* fwc = static_cast(m_formData->fm); -+ return !fwc->isCombo() ? fwc->isMultiSelect() : false; -+} -+ -+QList FormFieldChoice::currentChoices() const -+{ -+ FormWidgetChoice* fwc = static_cast(m_formData->fm); -+ int num = fwc->getNumChoices(); -+ QList choices; -+ for ( int i = 0; i < num; ++i ) -+ if ( fwc->isSelected( i ) ) -+ choices.append( i ); -+ return choices; -+} -+ -+void FormFieldChoice::setCurrentChoices( const QList &choice ) -+{ -+ FormWidgetChoice* fwc = static_cast(m_formData->fm); -+ fwc->deselectAll(); -+ for ( int i = 0; i < choice.count(); ++i ) -+ fwc->select( choice.at( i ) ); -+} -+ -+QString FormFieldChoice::editChoice() const -+{ -+ FormWidgetChoice* fwc = static_cast(m_formData->fm); -+ -+ if ( fwc->isCombo() && fwc->hasEdit() ) -+ return UnicodeParsedString(fwc->getEditChoice()); -+ else -+ return QString(); -+} -+ -+void FormFieldChoice::setEditChoice(const QString& text) -+{ -+ FormWidgetChoice* fwc = static_cast(m_formData->fm); -+ -+ if ( fwc->isCombo() && fwc->hasEdit() ) -+ { -+ GooString* goo = QStringToUnicodeGooString( text ); -+ fwc->setEditChoice( goo ); -+ delete goo; -+ } -+} -+ -+Qt::Alignment FormFieldChoice::textAlignment() const -+{ -+ return formTextAlignment(m_formData->fm); -+} -+ -+bool FormFieldChoice::canBeSpellChecked() const -+{ -+ FormWidgetChoice* fwc = static_cast(m_formData->fm); -+ return !fwc->noSpellCheck(); -+} -+ -+} -diff --git a/qt4/src/poppler-form.h b/qt4/src/poppler-form.h -new file mode 100644 -index 00000000..79ed3932 ---- /dev/null -+++ b/qt4/src/poppler-form.h -@@ -0,0 +1,343 @@ -+/* poppler-form.h: qt4 interface to poppler -+ * Copyright (C) 2007-2008, Pino Toscano -+ * Copyright (C) 2008, 2011, Albert Astals Cid -+ * Copyright (C) 2012, Adam Reichold -+ * -+ * 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_QT4_FORM_H_ -+#define _POPPLER_QT4_FORM_H_ -+ -+#include -+#include -+#include "poppler-export.h" -+ -+class Page; -+class FormWidget; -+class FormWidgetButton; -+class FormWidgetText; -+class FormWidgetChoice; -+ -+namespace Poppler { -+ -+ class DocumentData; -+ class Link; -+ -+ class FormFieldData; -+ /** -+ The base class representing a form field. -+ -+ \since 0.6 -+ */ -+ class POPPLER_QT4_EXPORT FormField { -+ public: -+ -+ /** -+ The different types of form field. -+ */ -+ enum FormType { -+ FormButton, ///< A button field. See \ref Poppler::FormFieldButton::ButtonType "ButtonType" -+ FormText, ///< A text field. See \ref Poppler::FormFieldText::TextType "TextType" -+ FormChoice, ///< A single choice field. See \ref Poppler::FormFieldChoice::ChoiceType "ChoiceType" -+ FormSignature ///< A signature field. -+ }; -+ -+ virtual ~FormField(); -+ -+ /** -+ The type of the field. -+ */ -+ virtual FormType type() const = 0; -+ -+ /** -+ \return The size of the field, in normalized coordinates, i.e. -+ [0..1] with regard to the dimensions (cropbox) of the page -+ */ -+ QRectF rect() const; -+ -+ /** -+ The ID of the field. -+ */ -+ int id() const; -+ -+ /** -+ The internal name of the field. -+ */ -+ QString name() const; -+ -+ /** -+ The internal fully qualified name of the field. -+ \since 0.18 -+ */ -+ QString fullyQualifiedName() const; -+ -+ /** -+ The name of the field to be used in user interface (eg messages to -+ the user). -+ */ -+ QString uiName() const; -+ -+ /** -+ Whether this form field is read-only. -+ */ -+ bool isReadOnly() const; -+ -+ /** -+ Whether this form field is visible. -+ */ -+ bool isVisible() const; -+ -+ /** -+ The activation action of this form field. -+ -+ \note It may be null. -+ */ -+ Link* activationAction() const; -+ -+ protected: -+ /// \cond PRIVATE -+ FormField(FormFieldData &dd); -+ -+ FormFieldData *m_formData; -+ /// \endcond -+ -+ private: -+ Q_DISABLE_COPY(FormField) -+ }; -+ -+ /** -+ A form field that represents a "button". -+ -+ \since 0.8 -+ */ -+ class POPPLER_QT4_EXPORT FormFieldButton : public FormField { -+ public: -+ -+ /** -+ * The types of button field. -+ */ -+ enum ButtonType -+ { -+ Push, ///< A simple push button. -+ CheckBox, ///< A check box. -+ Radio ///< A radio button. -+ }; -+ -+ /// \cond PRIVATE -+ FormFieldButton(DocumentData *doc, ::Page *p, ::FormWidgetButton *w); -+ /// \endcond -+ virtual ~FormFieldButton(); -+ -+ virtual FormType type() const; -+ -+ /** -+ The particular type of the button field. -+ */ -+ ButtonType buttonType() const; -+ -+ /** -+ * The caption to be used for the button. -+ */ -+ QString caption() const; -+ -+ /** -+ The state of the button. -+ */ -+ bool state() const; -+ -+ /** -+ Sets the state of the button to the new \p state . -+ */ -+ void setState( bool state ); -+ -+ /** -+ The list with the IDs of siblings (ie, buttons belonging to the same -+ group as the current one. -+ -+ Valid only for \ref Radio buttons, an empty list otherwise. -+ */ -+ QList siblings() const; -+ -+ private: -+ Q_DISABLE_COPY(FormFieldButton) -+ }; -+ -+ /** -+ A form field that represents a text input. -+ -+ \since 0.6 -+ */ -+ class POPPLER_QT4_EXPORT FormFieldText : public FormField { -+ public: -+ -+ /** -+ The particular type of this text field. -+ */ -+ enum TextType { -+ Normal, ///< A simple singleline text field. -+ Multiline, ///< A multiline text field. -+ FileSelect ///< An input field to select the path of a file on disk. -+ }; -+ -+ /// \cond PRIVATE -+ FormFieldText(DocumentData *doc, ::Page *p, ::FormWidgetText *w); -+ /// \endcond -+ virtual ~FormFieldText(); -+ -+ virtual FormType type() const; -+ -+ /** -+ The text type of the text field. -+ */ -+ TextType textType() const; -+ -+ /** -+ The text associated with the text field. -+ */ -+ QString text() const; -+ -+ /** -+ Sets the text associated with the text field to the specified -+ \p text. -+ */ -+ void setText( const QString& text ); -+ -+ /** -+ Whether this text field is a password input, eg its text \b must be -+ replaced with asterisks. -+ -+ Always false for \ref FileSelect text fields. -+ */ -+ bool isPassword() const; -+ -+ /** -+ Whether this text field should allow rich text. -+ */ -+ bool isRichText() const; -+ -+ /** -+ The maximum length for the text of this field, or -1 if not set. -+ */ -+ int maximumLength() const; -+ -+ /** -+ The horizontal alignment for the text of this text field. -+ */ -+ Qt::Alignment textAlignment() const; -+ -+ /** -+ Whether the text inserted manually in the field (where possible) -+ can be spell-checked. -+ */ -+ bool canBeSpellChecked() const; -+ -+ private: -+ Q_DISABLE_COPY(FormFieldText) -+ }; -+ -+ /** -+ A form field that represents a choice field. -+ -+ \since 0.6 -+ */ -+ class POPPLER_QT4_EXPORT FormFieldChoice : public FormField { -+ public: -+ -+ /** -+ The particular type of this choice field. -+ */ -+ enum ChoiceType { -+ ComboBox, ///< A simple singleline text field. -+ ListBox ///< A multiline text field. -+ }; -+ -+ /// \cond PRIVATE -+ FormFieldChoice(DocumentData *doc, ::Page *p, ::FormWidgetChoice *w); -+ /// \endcond -+ virtual ~FormFieldChoice(); -+ -+ virtual FormType type() const; -+ -+ /** -+ The choice type of the choice field. -+ */ -+ ChoiceType choiceType() const; -+ -+ /** -+ The possible choices of the choice field. -+ */ -+ QStringList choices() const; -+ -+ /** -+ Whether this FormFieldChoice::ComboBox is editable, i.e. the user -+ can type in a custom value. -+ -+ Always false for the other types of choices. -+ */ -+ bool isEditable() const; -+ -+ /** -+ Whether more than one choice of this FormFieldChoice::ListBox -+ can be selected at the same time. -+ -+ Always false for the other types of choices. -+ */ -+ bool multiSelect() const; -+ -+ /** -+ The currently selected choices. -+ */ -+ QList currentChoices() const; -+ -+ /** -+ Sets the selected choices to \p choice. -+ */ -+ void setCurrentChoices( const QList &choice ); -+ -+ /** -+ The text entered into an editable combo box choice field. Otherwise a null string. -+ -+ \since 0.22 -+ */ -+ QString editChoice() const; -+ -+ /** -+ Sets the text entered into an editable combo box choice field. Otherwise does nothing. -+ -+ \since 0.22 -+ */ -+ void setEditChoice(const QString& text); -+ -+ /** -+ The horizontal alignment for the text of this text field. -+ */ -+ Qt::Alignment textAlignment() const; -+ -+ /** -+ Whether the text inserted manually in the field (where possible) -+ can be spell-checked. -+ -+ Returns false if the field is not an editable text field. -+ */ -+ bool canBeSpellChecked() const; -+ -+ private: -+ Q_DISABLE_COPY(FormFieldChoice) -+ }; -+ -+} -+ -+#endif -diff --git a/qt4/src/poppler-link-extractor-private.h b/qt4/src/poppler-link-extractor-private.h -new file mode 100644 -index 00000000..32ddd038 ---- /dev/null -+++ b/qt4/src/poppler-link-extractor-private.h -@@ -0,0 +1,57 @@ -+/* poppler-link-extractor_p.h: qt interface to poppler -+ * Copyright (C) 2007, 2008, 2011, Pino Toscano -+ * -+ * 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_LINK_EXTRACTOR_H_ -+#define _POPPLER_LINK_EXTRACTOR_H_ -+ -+#include -+#include -+ -+#include -+ -+namespace Poppler -+{ -+ -+class Link; -+class PageData; -+ -+class LinkExtractorOutputDev : public OutputDev -+{ -+ public: -+ LinkExtractorOutputDev(PageData *data); -+ virtual ~LinkExtractorOutputDev(); -+ -+ // inherited from OutputDev -+ virtual bool upsideDown() { return false; } -+ virtual bool useDrawChar() { return false; } -+ virtual bool interpretType3Chars() { return false; } -+ virtual void processLink(::AnnotLink *link); -+ -+ // our stuff -+ QList< Link* > links(); -+ -+ private: -+ PageData *m_data; -+ double m_pageCropWidth; -+ double m_pageCropHeight; -+ QList< Link* > m_links; -+}; -+ -+} -+ -+#endif -diff --git a/qt4/src/poppler-link-extractor.cc b/qt4/src/poppler-link-extractor.cc -new file mode 100644 -index 00000000..0b1563b6 ---- /dev/null -+++ b/qt4/src/poppler-link-extractor.cc -@@ -0,0 +1,84 @@ -+/* poppler-link-extractor_p.h: qt interface to poppler -+ * Copyright (C) 2007, 2008, 2011, Pino Toscano -+ * Copyright (C) 2008, Albert Astals Cid -+ * -+ * 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-link-extractor-private.h" -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "poppler-qt4.h" -+#include "poppler-page-private.h" -+ -+namespace Poppler -+{ -+ -+LinkExtractorOutputDev::LinkExtractorOutputDev(PageData *data) -+ : m_data(data) -+{ -+ Q_ASSERT(m_data); -+ ::Page *popplerPage = m_data->page; -+ m_pageCropWidth = popplerPage->getCropWidth(); -+ m_pageCropHeight = popplerPage->getCropHeight(); -+ if (popplerPage->getRotate() == 90 || popplerPage->getRotate() == 270) -+ qSwap(m_pageCropWidth, m_pageCropHeight); -+ GfxState gfxState(72.0, 72.0, popplerPage->getCropBox(), popplerPage->getRotate(), true); -+ setDefaultCTM(gfxState.getCTM()); -+} -+ -+LinkExtractorOutputDev::~LinkExtractorOutputDev() -+{ -+ qDeleteAll(m_links); -+} -+ -+void LinkExtractorOutputDev::processLink(::AnnotLink *link) -+{ -+ if (!link->isOk()) -+ return; -+ -+ double left, top, right, bottom; -+ int leftAux, topAux, rightAux, bottomAux; -+ link->getRect(&left, &top, &right, &bottom); -+ QRectF linkArea; -+ -+ cvtUserToDev(left, top, &leftAux, &topAux); -+ cvtUserToDev(right, bottom, &rightAux, &bottomAux); -+ linkArea.setLeft((double)leftAux / m_pageCropWidth); -+ linkArea.setTop((double)topAux / m_pageCropHeight); -+ linkArea.setRight((double)rightAux / m_pageCropWidth); -+ linkArea.setBottom((double)bottomAux / m_pageCropHeight); -+ -+ Link *popplerLink = m_data->convertLinkActionToLink(link->getAction(), linkArea); -+ if (popplerLink) -+ { -+ m_links.append(popplerLink); -+ } -+ OutputDev::processLink(link); -+} -+ -+QList< Link* > LinkExtractorOutputDev::links() -+{ -+ QList< Link* > ret = m_links; -+ m_links.clear(); -+ return ret; -+} -+ -+} -diff --git a/qt4/src/poppler-link-private.h b/qt4/src/poppler-link-private.h -new file mode 100644 -index 00000000..7b03c1c3 ---- /dev/null -+++ b/qt4/src/poppler-link-private.h -@@ -0,0 +1,57 @@ -+/* poppler-link-private.h: qt interface to poppler -+ * Copyright (C) 2016, Albert Astals Cid -+ * -+ * 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_LINK_PRIVATE_H_ -+#define _POPPLER_LINK_PRIVATE_H_ -+ -+class LinkOCGState; -+ -+namespace Poppler { -+ -+class LinkPrivate -+{ -+public: -+ LinkPrivate( const QRectF &area ) -+ : linkArea( area ) -+ { -+ } -+ -+ virtual ~LinkPrivate() -+ { -+ } -+ -+ QRectF linkArea; -+}; -+ -+ -+ -+class LinkOCGStatePrivate : public LinkPrivate -+{ -+public: -+ LinkOCGStatePrivate( const QRectF &area, ::LinkOCGState *plocg ) -+ : LinkPrivate( area ) -+ , popplerLinkOCGState( plocg ) -+ { -+ } -+ -+ ::LinkOCGState *popplerLinkOCGState; -+}; -+ -+} -+ -+#endif -diff --git a/qt4/src/poppler-link.cc b/qt4/src/poppler-link.cc -new file mode 100644 -index 00000000..1e37f5bd ---- /dev/null -+++ b/qt4/src/poppler-link.cc -@@ -0,0 +1,705 @@ -+/* poppler-link.cc: qt interface to poppler -+ * Copyright (C) 2006-2007, 2016, 2017, Albert Astals Cid -+ * Copyright (C) 2007-2008, Pino Toscano -+ * Copyright (C) 2010 Hib Eris -+ * Copyright (C) 2012, Tobias Koenig -+ * Copyright (C) 2012, Guillermo A. Amaral B. -+ * Adapting code from -+ * Copyright (C) 2004 by Enrico Ros -+ * -+ * 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 -+#include -+#include -+#include -+ -+#include -+ -+#include "poppler-annotation-private.h" -+ -+#include "Link.h" -+#include "Rendition.h" -+ -+namespace Poppler { -+ -+class LinkDestinationPrivate : public QSharedData -+{ -+ public: -+ LinkDestinationPrivate(); -+ -+ LinkDestination::Kind kind; // destination type -+ QString name; -+ int pageNum; // page number -+ double left, bottom; // position -+ double right, top; -+ double zoom; // zoom factor -+ bool changeLeft : 1, changeTop : 1; // for destXYZ links, which position -+ bool changeZoom : 1; // components to change -+}; -+ -+ LinkDestinationPrivate::LinkDestinationPrivate() -+ { -+ // sane defaults -+ kind = LinkDestination::destXYZ; -+ pageNum = 0; -+ left = 0; -+ bottom = 0; -+ right = 0; -+ top = 0; -+ zoom = 1; -+ changeLeft = true; -+ changeTop = true; -+ changeZoom = false; -+ } -+ -+class LinkGotoPrivate : public LinkPrivate -+{ -+ public: -+ LinkGotoPrivate( const QRectF &area, const LinkDestination &dest ); -+ -+ QString extFileName; -+ LinkDestination destination; -+}; -+ -+ LinkGotoPrivate::LinkGotoPrivate( const QRectF &area, const LinkDestination &dest ) -+ : LinkPrivate( area ), destination( dest ) -+ { -+ } -+ -+class LinkExecutePrivate : public LinkPrivate -+{ -+ public: -+ LinkExecutePrivate( const QRectF &area ); -+ -+ QString fileName; -+ QString parameters; -+}; -+ -+ LinkExecutePrivate::LinkExecutePrivate( const QRectF &area ) -+ : LinkPrivate( area ) -+ { -+ } -+ -+class LinkBrowsePrivate : public LinkPrivate -+{ -+ public: -+ LinkBrowsePrivate( const QRectF &area ); -+ -+ QString url; -+}; -+ -+ LinkBrowsePrivate::LinkBrowsePrivate( const QRectF &area ) -+ : LinkPrivate( area ) -+ { -+ } -+ -+class LinkActionPrivate : public LinkPrivate -+{ -+ public: -+ LinkActionPrivate( const QRectF &area ); -+ -+ LinkAction::ActionType type; -+}; -+ -+ LinkActionPrivate::LinkActionPrivate( const QRectF &area ) -+ : LinkPrivate( area ) -+ { -+ } -+ -+class LinkSoundPrivate : public LinkPrivate -+{ -+ public: -+ LinkSoundPrivate( const QRectF &area ); -+ ~LinkSoundPrivate(); -+ -+ double volume; -+ bool sync : 1; -+ bool repeat : 1; -+ bool mix : 1; -+ SoundObject *sound; -+}; -+ -+ LinkSoundPrivate::LinkSoundPrivate( const QRectF &area ) -+ : LinkPrivate( area ), sound( 0 ) -+ { -+ } -+ -+ LinkSoundPrivate::~LinkSoundPrivate() -+ { -+ delete sound; -+ } -+ -+class LinkRenditionPrivate : public LinkPrivate -+{ -+ public: -+ LinkRenditionPrivate( const QRectF &area, ::MediaRendition *rendition, ::LinkRendition::RenditionOperation operation, const QString &script, const Ref &annotationReference ); -+ ~LinkRenditionPrivate(); -+ -+ MediaRendition *rendition; -+ LinkRendition::RenditionAction action; -+ QString script; -+ Ref annotationReference; -+}; -+ -+ LinkRenditionPrivate::LinkRenditionPrivate( const QRectF &area, ::MediaRendition *r, ::LinkRendition::RenditionOperation operation, const QString &javaScript, const Ref &ref ) -+ : LinkPrivate( area ) -+ , rendition( r ? new MediaRendition( r ) : 0 ) -+ , action( LinkRendition::PlayRendition ) -+ , script( javaScript ) -+ , annotationReference( ref ) -+ { -+ switch ( operation ) -+ { -+ case ::LinkRendition::NoRendition: -+ action = LinkRendition::NoRendition; -+ break; -+ case ::LinkRendition::PlayRendition: -+ action = LinkRendition::PlayRendition; -+ break; -+ case ::LinkRendition::StopRendition: -+ action = LinkRendition::StopRendition; -+ break; -+ case ::LinkRendition::PauseRendition: -+ action = LinkRendition::PauseRendition; -+ break; -+ case ::LinkRendition::ResumeRendition: -+ action = LinkRendition::ResumeRendition; -+ break; -+ } -+ } -+ -+ LinkRenditionPrivate::~LinkRenditionPrivate() -+ { -+ delete rendition; -+ } -+ -+class LinkJavaScriptPrivate : public LinkPrivate -+{ -+ public: -+ LinkJavaScriptPrivate( const QRectF &area ); -+ -+ QString js; -+}; -+ -+ LinkJavaScriptPrivate::LinkJavaScriptPrivate( const QRectF &area ) -+ : LinkPrivate( area ) -+ { -+ } -+ -+class LinkMoviePrivate : public LinkPrivate -+{ -+ public: -+ LinkMoviePrivate( const QRectF &area, LinkMovie::Operation operation, const QString &title, const Ref &reference ); -+ -+ LinkMovie::Operation operation; -+ QString annotationTitle; -+ Ref annotationReference; -+}; -+ -+ LinkMoviePrivate::LinkMoviePrivate( const QRectF &area, LinkMovie::Operation _operation, const QString &title, const Ref &reference ) -+ : LinkPrivate( area ), operation( _operation ), annotationTitle( title ), annotationReference( reference ) -+ { -+ } -+ -+ static void cvtUserToDev(::Page *page, double xu, double yu, int *xd, int *yd) { -+ double ctm[6]; -+ -+ page->getDefaultCTM(ctm, 72.0, 72.0, 0, false, true); -+ *xd = (int)(ctm[0] * xu + ctm[2] * yu + ctm[4] + 0.5); -+ *yd = (int)(ctm[1] * xu + ctm[3] * yu + ctm[5] + 0.5); -+ } -+ -+ LinkDestination::LinkDestination(const LinkDestinationData &data) -+ : d( new LinkDestinationPrivate ) -+ { -+ bool deleteDest = false; -+ const LinkDest *ld = data.ld; -+ -+ if ( data.namedDest && !ld && !data.externalDest ) -+ { -+ deleteDest = true; -+ ld = data.doc->doc->findDest( data.namedDest ); -+ } -+ // in case this destination was named one, and it was not resolved -+ if ( data.namedDest && !ld ) -+ { -+ d->name = QString::fromLatin1( data.namedDest->c_str() ); -+ } -+ -+ if (!ld) return; -+ -+ if (ld->getKind() == ::destXYZ) d->kind = destXYZ; -+ else if (ld->getKind() == ::destFit) d->kind = destFit; -+ else if (ld->getKind() == ::destFitH) d->kind = destFitH; -+ else if (ld->getKind() == ::destFitV) d->kind = destFitV; -+ else if (ld->getKind() == ::destFitR) d->kind = destFitR; -+ else if (ld->getKind() == ::destFitB) d->kind = destFitB; -+ else if (ld->getKind() == ::destFitBH) d->kind = destFitBH; -+ else if (ld->getKind() == ::destFitBV) d->kind = destFitBV; -+ -+ if ( !ld->isPageRef() ) d->pageNum = ld->getPageNum(); -+ else -+ { -+ Ref ref = ld->getPageRef(); -+ d->pageNum = data.doc->doc->findPage( ref ); -+ } -+ double left = ld->getLeft(); -+ double bottom = ld->getBottom(); -+ double right = ld->getRight(); -+ double top = ld->getTop(); -+ d->zoom = ld->getZoom(); -+ d->changeLeft = ld->getChangeLeft(); -+ d->changeTop = ld->getChangeTop(); -+ d->changeZoom = ld->getChangeZoom(); -+ -+ int leftAux = 0, topAux = 0, rightAux = 0, bottomAux = 0; -+ -+ if (!data.externalDest) { -+ ::Page *page; -+ if (d->pageNum > 0 && -+ d->pageNum <= data.doc->doc->getNumPages() && -+ (page = data.doc->doc->getPage( d->pageNum ))) -+ { -+ cvtUserToDev( page, left, top, &leftAux, &topAux ); -+ cvtUserToDev( page, right, bottom, &rightAux, &bottomAux ); -+ -+ d->left = leftAux / (double)page->getCropWidth(); -+ d->top = topAux / (double)page->getCropHeight(); -+ d->right = rightAux/ (double)page->getCropWidth(); -+ d->bottom = bottomAux / (double)page->getCropHeight(); -+ } -+ else d->pageNum = 0; -+ } -+ -+ if (deleteDest) delete ld; -+ } -+ -+ LinkDestination::LinkDestination(const QString &description) -+ : d( new LinkDestinationPrivate ) -+ { -+ QStringList tokens = description.split( ';' ); -+ d->kind = static_cast(tokens.at(0).toInt()); -+ d->pageNum = tokens.at(1).toInt(); -+ d->left = tokens.at(2).toDouble(); -+ d->bottom = tokens.at(3).toDouble(); -+ d->right = tokens.at(4).toDouble(); -+ d->top = tokens.at(5).toDouble(); -+ d->zoom = tokens.at(6).toDouble(); -+ d->changeLeft = static_cast(tokens.at(7).toInt()); -+ d->changeTop = static_cast(tokens.at(8).toInt()); -+ d->changeZoom = static_cast(tokens.at(9).toInt()); -+ } -+ -+ LinkDestination::LinkDestination(const LinkDestination &other) -+ : d( other.d ) -+ { -+ } -+ -+ LinkDestination::~LinkDestination() -+ { -+ } -+ -+ LinkDestination::Kind LinkDestination::kind() const -+ { -+ return d->kind; -+ } -+ -+ int LinkDestination::pageNumber() const -+ { -+ return d->pageNum; -+ } -+ -+ double LinkDestination::left() const -+ { -+ return d->left; -+ } -+ -+ double LinkDestination::bottom() const -+ { -+ return d->bottom; -+ } -+ -+ double LinkDestination::right() const -+ { -+ return d->right; -+ } -+ -+ double LinkDestination::top() const -+ { -+ return d->top; -+ } -+ -+ double LinkDestination::zoom() const -+ { -+ return d->zoom; -+ } -+ -+ bool LinkDestination::isChangeLeft() const -+ { -+ return d->changeLeft; -+ } -+ -+ bool LinkDestination::isChangeTop() const -+ { -+ return d->changeTop; -+ } -+ -+ bool LinkDestination::isChangeZoom() const -+ { -+ return d->changeZoom; -+ } -+ -+ QString LinkDestination::toString() const -+ { -+ QString s = QString::number( (qint8)d->kind ); -+ s += ";" + QString::number( d->pageNum ); -+ s += ";" + QString::number( d->left ); -+ s += ";" + QString::number( d->bottom ); -+ s += ";" + QString::number( d->right ); -+ s += ";" + QString::number( d->top ); -+ s += ";" + QString::number( d->zoom ); -+ s += ";" + QString::number( (qint8)d->changeLeft ); -+ s += ";" + QString::number( (qint8)d->changeTop ); -+ s += ";" + QString::number( (qint8)d->changeZoom ); -+ return s; -+ } -+ -+ QString LinkDestination::destinationName() const -+ { -+ return d->name; -+ } -+ -+ LinkDestination& LinkDestination::operator=(const LinkDestination &other) -+ { -+ if ( this == &other ) -+ return *this; -+ -+ d = other.d; -+ return *this; -+ } -+ -+ -+ // Link -+ Link::~Link() -+ { -+ delete d_ptr; -+ } -+ -+ Link::Link(const QRectF &linkArea) -+ : d_ptr( new LinkPrivate( linkArea ) ) -+ { -+ } -+ -+ Link::Link( LinkPrivate &dd ) -+ : d_ptr( &dd ) -+ { -+ } -+ -+ Link::LinkType Link::linkType() const -+ { -+ return None; -+ } -+ -+ QRectF Link::linkArea() const -+ { -+ Q_D( const Link ); -+ return d->linkArea; -+ } -+ -+ // LinkGoto -+ LinkGoto::LinkGoto( const QRectF &linkArea, QString extFileName, const LinkDestination & destination ) -+ : Link( *new LinkGotoPrivate( linkArea, destination ) ) -+ { -+ Q_D( LinkGoto ); -+ d->extFileName = extFileName; -+ } -+ -+ LinkGoto::~LinkGoto() -+ { -+ } -+ -+ bool LinkGoto::isExternal() const -+ { -+ Q_D( const LinkGoto ); -+ return !d->extFileName.isEmpty(); -+ } -+ -+ QString LinkGoto::fileName() const -+ { -+ Q_D( const LinkGoto ); -+ return d->extFileName; -+ } -+ -+ LinkDestination LinkGoto::destination() const -+ { -+ Q_D( const LinkGoto ); -+ return d->destination; -+ } -+ -+ Link::LinkType LinkGoto::linkType() const -+ { -+ return Goto; -+ } -+ -+ // LinkExecute -+ LinkExecute::LinkExecute( const QRectF &linkArea, const QString & file, const QString & params ) -+ : Link( *new LinkExecutePrivate( linkArea ) ) -+ { -+ Q_D( LinkExecute ); -+ d->fileName = file; -+ d->parameters = params; -+ } -+ -+ LinkExecute::~LinkExecute() -+ { -+ } -+ -+ QString LinkExecute::fileName() const -+ { -+ Q_D( const LinkExecute ); -+ return d->fileName; -+ } -+ QString LinkExecute::parameters() const -+ { -+ Q_D( const LinkExecute ); -+ return d->parameters; -+ } -+ -+ Link::LinkType LinkExecute::linkType() const -+ { -+ return Execute; -+ } -+ -+ // LinkBrowse -+ LinkBrowse::LinkBrowse( const QRectF &linkArea, const QString &url ) -+ : Link( *new LinkBrowsePrivate( linkArea ) ) -+ { -+ Q_D( LinkBrowse ); -+ d->url = url; -+ } -+ -+ LinkBrowse::~LinkBrowse() -+ { -+ } -+ -+ QString LinkBrowse::url() const -+ { -+ Q_D( const LinkBrowse ); -+ return d->url; -+ } -+ -+ Link::LinkType LinkBrowse::linkType() const -+ { -+ return Browse; -+ } -+ -+ // LinkAction -+ LinkAction::LinkAction( const QRectF &linkArea, ActionType actionType ) -+ : Link( *new LinkActionPrivate( linkArea ) ) -+ { -+ Q_D( LinkAction ); -+ d->type = actionType; -+ } -+ -+ LinkAction::~LinkAction() -+ { -+ } -+ -+ LinkAction::ActionType LinkAction::actionType() const -+ { -+ Q_D( const LinkAction ); -+ return d->type; -+ } -+ -+ Link::LinkType LinkAction::linkType() const -+ { -+ return Action; -+ } -+ -+ // LinkSound -+ LinkSound::LinkSound( const QRectF &linkArea, double volume, bool sync, bool repeat, bool mix, SoundObject *sound ) -+ : Link( *new LinkSoundPrivate( linkArea ) ) -+ { -+ Q_D( LinkSound ); -+ d->volume = volume; -+ d->sync = sync; -+ d->repeat = repeat; -+ d->mix = mix; -+ d->sound = sound; -+ } -+ -+ LinkSound::~LinkSound() -+ { -+ } -+ -+ Link::LinkType LinkSound::linkType() const -+ { -+ return Sound; -+ } -+ -+ double LinkSound::volume() const -+ { -+ Q_D( const LinkSound ); -+ return d->volume; -+ } -+ -+ bool LinkSound::synchronous() const -+ { -+ Q_D( const LinkSound ); -+ return d->sync; -+ } -+ -+ bool LinkSound::repeat() const -+ { -+ Q_D( const LinkSound ); -+ return d->repeat; -+ } -+ -+ bool LinkSound::mix() const -+ { -+ Q_D( const LinkSound ); -+ return d->mix; -+ } -+ -+ SoundObject *LinkSound::sound() const -+ { -+ Q_D( const LinkSound ); -+ return d->sound; -+ } -+ -+ // LinkRendition -+ LinkRendition::LinkRendition( const QRectF &linkArea, ::MediaRendition *rendition ) -+ : Link( *new LinkRenditionPrivate( linkArea, rendition, ::LinkRendition::NoRendition, QString(), Ref() ) ) -+ { -+ } -+ -+ LinkRendition::LinkRendition( const QRectF &linkArea, ::MediaRendition *rendition, int operation, const QString &script, const Ref &annotationReference ) -+ : Link( *new LinkRenditionPrivate( linkArea, rendition, static_cast(operation), script, annotationReference ) ) -+ { -+ } -+ -+ LinkRendition::~LinkRendition() -+ { -+ } -+ -+ Link::LinkType LinkRendition::linkType() const -+ { -+ return Rendition; -+ } -+ -+ MediaRendition * LinkRendition::rendition() const -+ { -+ Q_D( const LinkRendition ); -+ return d->rendition; -+ } -+ -+ LinkRendition::RenditionAction LinkRendition::action() const -+ { -+ Q_D( const LinkRendition ); -+ return d->action; -+ } -+ -+ QString LinkRendition::script() const -+ { -+ Q_D( const LinkRendition ); -+ return d->script; -+ } -+ -+ bool LinkRendition::isReferencedAnnotation( const ScreenAnnotation *annotation ) const -+ { -+ Q_D( const LinkRendition ); -+ if ( d->annotationReference.num != -1 && d->annotationReference == annotation->d_ptr->pdfObjectReference() ) -+ { -+ return true; -+ } -+ -+ return false; -+ } -+ -+ // LinkJavaScript -+ LinkJavaScript::LinkJavaScript( const QRectF &linkArea, const QString &js ) -+ : Link( *new LinkJavaScriptPrivate( linkArea ) ) -+ { -+ Q_D( LinkJavaScript ); -+ d->js = js; -+ } -+ -+ LinkJavaScript::~LinkJavaScript() -+ { -+ } -+ -+ Link::LinkType LinkJavaScript::linkType() const -+ { -+ return JavaScript; -+ } -+ -+ QString LinkJavaScript::script() const -+ { -+ Q_D( const LinkJavaScript ); -+ return d->js; -+ } -+ -+ // LinkMovie -+ LinkMovie::LinkMovie( const QRectF &linkArea, Operation operation, const QString &annotationTitle, const Ref &annotationReference ) -+ : Link( *new LinkMoviePrivate( linkArea, operation, annotationTitle, annotationReference ) ) -+ { -+ } -+ -+ LinkMovie::~LinkMovie() -+ { -+ } -+ -+ Link::LinkType LinkMovie::linkType() const -+ { -+ return Movie; -+ } -+ -+ LinkMovie::Operation LinkMovie::operation() const -+ { -+ Q_D( const LinkMovie ); -+ return d->operation; -+ } -+ -+ bool LinkMovie::isReferencedAnnotation( const MovieAnnotation *annotation ) const -+ { -+ Q_D( const LinkMovie ); -+ if ( d->annotationReference.num != -1 && d->annotationReference == annotation->d_ptr->pdfObjectReference() ) -+ { -+ return true; -+ } -+ else if ( !d->annotationTitle.isNull() ) -+ { -+ return ( annotation->movieTitle() == d->annotationTitle ); -+ } -+ -+ return false; -+ } -+ -+ LinkOCGState::LinkOCGState( LinkOCGStatePrivate *ocgp ) -+ : Link ( *ocgp ) -+ { -+ } -+ -+ LinkOCGState::~LinkOCGState() -+ { -+ } -+ -+ Link::LinkType LinkOCGState::linkType() const -+ { -+ return OCGState; -+ } -+} -diff --git a/qt4/src/poppler-link.h b/qt4/src/poppler-link.h -new file mode 100644 -index 00000000..42a8c1fc ---- /dev/null -+++ b/qt4/src/poppler-link.h -@@ -0,0 +1,641 @@ -+/* poppler-link.h: qt interface to poppler -+ * Copyright (C) 2006, 2013, 2016, Albert Astals Cid -+ * Copyright (C) 2007-2008, 2010, Pino Toscano -+ * Copyright (C) 2010, 2012, Guillermo Amaral -+ * Copyright (C) 2012, Tobias Koenig -+ * Adapting code from -+ * Copyright (C) 2004 by Enrico Ros -+ * -+ * 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_LINK_H_ -+#define _POPPLER_LINK_H_ -+ -+#include -+#include -+#include -+#include "poppler-export.h" -+ -+struct Ref; -+class MediaRendition; -+class MovieAnnotation; -+class ScreenAnnotation; -+ -+namespace Poppler { -+ -+class LinkPrivate; -+class LinkGotoPrivate; -+class LinkExecutePrivate; -+class LinkBrowsePrivate; -+class LinkActionPrivate; -+class LinkSoundPrivate; -+class LinkJavaScriptPrivate; -+class LinkMoviePrivate; -+class LinkDestinationData; -+class LinkDestinationPrivate; -+class LinkRenditionPrivate; -+class LinkOCGStatePrivate; -+class MediaRendition; -+class SoundObject; -+ -+/** -+ * \short A destination. -+ * -+ * The LinkDestination class represent a "destination" (in terms of visual -+ * viewport to be displayed) for \link Poppler::LinkGoto GoTo\endlink links, -+ * and items in the table of contents (TOC) of a document. -+ * -+ * Coordinates are in 0..1 range -+ */ -+class POPPLER_QT4_EXPORT LinkDestination -+{ -+ public: -+ /** -+ * The possible kind of "viewport destination". -+ */ -+ enum Kind -+ { -+ /** -+ * The new viewport is specified in terms of: -+ * - possibile new left coordinate (see isChangeLeft() ) -+ * - possibile new top coordinate (see isChangeTop() ) -+ * - possibile new zoom level (see isChangeZoom() ) -+ */ -+ destXYZ = 1, -+ destFit = 2, -+ destFitH = 3, -+ destFitV = 4, -+ destFitR = 5, -+ destFitB = 6, -+ destFitBH = 7, -+ destFitBV = 8 -+ }; -+ -+ /// \cond PRIVATE -+ LinkDestination(const LinkDestinationData &data); -+ LinkDestination(const QString &description); -+ /// \endcond -+ /** -+ * Copy constructor. -+ */ -+ LinkDestination(const LinkDestination &other); -+ /** -+ * Destructor. -+ */ -+ ~LinkDestination(); -+ -+ // Accessors. -+ /** -+ * The kind of destination. -+ */ -+ Kind kind() const; -+ /** -+ * Which page is the target of this destination. -+ * -+ * \note this number is 1-based, so for a 5 pages document the -+ * valid page numbers go from 1 to 5 (both included). -+ */ -+ int pageNumber() const; -+ /** -+ * The new left for the viewport of the target page, in case -+ * it is specified to be changed (see isChangeLeft() ) -+ */ -+ double left() const; -+ double bottom() const; -+ double right() const; -+ /** -+ * The new top for the viewport of the target page, in case -+ * it is specified to be changed (see isChangeTop() ) -+ */ -+ double top() const; -+ double zoom() const; -+ /** -+ * Whether the left of the viewport on the target page should -+ * be changed. -+ * -+ * \see left() -+ */ -+ bool isChangeLeft() const; -+ /** -+ * Whether the top of the viewport on the target page should -+ * be changed. -+ * -+ * \see top() -+ */ -+ bool isChangeTop() const; -+ /** -+ * Whether the zoom level should be changed. -+ * -+ * \see zoom() -+ */ -+ bool isChangeZoom() const; -+ -+ /** -+ * Return a string repesentation of this destination. -+ */ -+ QString toString() const; -+ -+ /** -+ * Return the name of this destination. -+ * -+ * \since 0.12 -+ */ -+ QString destinationName() const; -+ -+ /** -+ * Assignment operator. -+ */ -+ LinkDestination& operator=(const LinkDestination &other); -+ -+ private: -+ QSharedDataPointer< LinkDestinationPrivate > d; -+}; -+ -+/** -+ * \short Encapsulates data that describes a link. -+ * -+ * This is the base class for links. It makes mandatory for inherited -+ * kind of links to reimplement the linkType() method and return the type of -+ * the link described by the reimplemented class. -+ */ -+class POPPLER_QT4_EXPORT Link -+{ -+ friend class OptContentModel; -+ -+ public: -+ /// \cond PRIVATE -+ Link( const QRectF &linkArea ); -+ /// \endcond -+ -+ /** -+ * The possible kinds of link. -+ * -+ * Inherited classes must return an unique identifier -+ */ -+ enum LinkType -+ { -+ None, ///< Unknown link -+ Goto, ///< A "Go To" link -+ Execute, ///< A command to be executed -+ Browse, ///< An URL to be browsed (eg "http://poppler.freedesktop.org") -+ Action, ///< A "standard" action to be executed in the viewer -+ Sound, ///< A link representing a sound to be played -+ Movie, ///< An action to be executed on a movie -+ Rendition, ///< A rendition link \since 0.20 -+ JavaScript, ///< A JavaScript code to be interpreted \since 0.10 -+ OCGState ///< An Optional Content Group state change \since 0.50 -+ }; -+ -+ /** -+ * The type of this link. -+ */ -+ virtual LinkType linkType() const; -+ -+ /** -+ * Destructor. -+ */ -+ virtual ~Link(); -+ -+ /** -+ * The area of a Page where the link should be active. -+ * -+ * \note this can be a null rect, in this case the link represents -+ * a general action. The area is given in 0..1 range -+ */ -+ QRectF linkArea() const; -+ -+ protected: -+ /// \cond PRIVATE -+ Link( LinkPrivate &dd ); -+ Q_DECLARE_PRIVATE( Link ) -+ LinkPrivate *d_ptr; -+ /// \endcond -+ -+ private: -+ Q_DISABLE_COPY( Link ) -+}; -+ -+ -+/** -+ * \brief Viewport reaching request. -+ * -+ * With a LinkGoto link, the document requests the specified viewport to be -+ * reached (aka, displayed in a viewer). Furthermore, if a file name is specified, -+ * then the destination refers to that document (and not to the document the -+ * current LinkGoto belongs to). -+ */ -+class POPPLER_QT4_EXPORT LinkGoto : public Link -+{ -+ public: -+ /** -+ * Create a new Goto link. -+ * -+ * \param linkArea the active area of the link -+ * \param extFileName if not empty, the file name to be open -+ * \param destination the destination to be reached -+ */ -+ LinkGoto( const QRectF &linkArea, QString extFileName, const LinkDestination & destination ); -+ /** -+ * Destructor. -+ */ -+ ~LinkGoto(); -+ -+ /** -+ * Whether the destination is in an external document -+ * (i.e. not the current document) -+ */ -+ bool isExternal() const; -+ // query for goto parameters -+ /** -+ * The file name of the document the destination() refers to, -+ * or an empty string in case it refers to the current document. -+ */ -+ QString fileName() const; -+ /** -+ * The destination to reach. -+ */ -+ LinkDestination destination() const; -+ LinkType linkType() const override; -+ -+ private: -+ Q_DECLARE_PRIVATE( LinkGoto ) -+ Q_DISABLE_COPY( LinkGoto ) -+}; -+ -+/** -+ * \brief Generic execution request. -+ * -+ * The LinkExecute link represent a "file name" execution request. The result -+ * depends on the \link fileName() file name\endlink: -+ * - if it is a document, then it is requested to be open -+ * - otherwise, it represents an executable to be run with the specified parameters -+ */ -+class POPPLER_QT4_EXPORT LinkExecute : public Link -+{ -+ public: -+ /** -+ * The file name to be executed -+ */ -+ QString fileName() const; -+ /** -+ * The parameters for the command. -+ */ -+ QString parameters() const; -+ -+ /** -+ * Create a new Execute link. -+ * -+ * \param linkArea the active area of the link -+ * \param file the file name to be open, or the program to be execute -+ * \param params the parameters for the program to execute -+ */ -+ LinkExecute( const QRectF &linkArea, const QString & file, const QString & params ); -+ /** -+ * Destructor. -+ */ -+ ~LinkExecute(); -+ LinkType linkType() const; -+ -+ private: -+ Q_DECLARE_PRIVATE( LinkExecute ) -+ Q_DISABLE_COPY( LinkExecute ) -+}; -+ -+/** -+ * \brief An URL to browse. -+ * -+ * The LinkBrowse link holds a URL (eg 'http://poppler.freedesktop.org', -+ * 'mailto:john@some.org', etc) to be open. -+ * -+ * The format of the URL is specified by RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt) -+ */ -+class POPPLER_QT4_EXPORT LinkBrowse : public Link -+{ -+ public: -+ /** -+ * The URL to open -+ */ -+ QString url() const; -+ -+ /** -+ * Create a new browse link. -+ * -+ * \param linkArea the active area of the link -+ * \param url the URL to be open -+ */ -+ LinkBrowse( const QRectF &linkArea, const QString &url ); -+ /** -+ * Destructor. -+ */ -+ ~LinkBrowse(); -+ LinkType linkType() const; -+ -+ private: -+ Q_DECLARE_PRIVATE( LinkBrowse ) -+ Q_DISABLE_COPY( LinkBrowse ) -+}; -+ -+/** -+ * \brief "Standard" action request. -+ * -+ * The LinkAction class represents a link that request a "standard" action -+ * to be performed by the viewer on the displayed document. -+ */ -+class POPPLER_QT4_EXPORT LinkAction : public Link -+{ -+ public: -+ /** -+ * The possible types of actions -+ */ -+ enum ActionType { PageFirst = 1, -+ PagePrev = 2, -+ PageNext = 3, -+ PageLast = 4, -+ HistoryBack = 5, -+ HistoryForward = 6, -+ Quit = 7, -+ Presentation = 8, -+ EndPresentation = 9, -+ Find = 10, -+ GoToPage = 11, -+ Close = 12, -+ Print = 13 ///< \since 0.16 -+ }; -+ -+ /** -+ * The action of the current LinkAction -+ */ -+ ActionType actionType() const; -+ -+ /** -+ * Create a new Action link, that executes a specified action -+ * on the document. -+ * -+ * \param linkArea the active area of the link -+ * \param actionType which action should be executed -+ */ -+ LinkAction( const QRectF &linkArea, ActionType actionType ); -+ /** -+ * Destructor. -+ */ -+ ~LinkAction(); -+ LinkType linkType() const; -+ -+ private: -+ Q_DECLARE_PRIVATE( LinkAction ) -+ Q_DISABLE_COPY( LinkAction ) -+}; -+ -+/** -+ * Sound: a sound to be played. -+ * -+ * \since 0.6 -+ */ -+class POPPLER_QT4_EXPORT LinkSound : public Link -+{ -+ public: -+ // create a Link_Sound -+ LinkSound( const QRectF &linkArea, double volume, bool sync, bool repeat, bool mix, SoundObject *sound ); -+ /** -+ * Destructor. -+ */ -+ virtual ~LinkSound(); -+ -+ LinkType linkType() const; -+ -+ /** -+ * The volume to be used when playing the sound. -+ * -+ * The volume is in the range [ -1, 1 ], where: -+ * - a negative number: no volume (mute) -+ * - 1: full volume -+ */ -+ double volume() const; -+ /** -+ * Whether the playback of the sound should be synchronous -+ * (thus blocking, waiting for the end of the sound playback). -+ */ -+ bool synchronous() const; -+ /** -+ * Whether the sound should be played continuously (that is, -+ * started again when it ends) -+ */ -+ bool repeat() const; -+ /** -+ * Whether the playback of this sound can be mixed with -+ * playbacks with other sounds of the same document. -+ * -+ * \note When false, any other playback must be stopped before -+ * playing the sound. -+ */ -+ bool mix() const; -+ /** -+ * The sound object to be played -+ */ -+ SoundObject *sound() const; -+ -+ private: -+ Q_DECLARE_PRIVATE( LinkSound ) -+ Q_DISABLE_COPY( LinkSound ) -+}; -+ -+/** -+ * Rendition: Rendition link. -+ * -+ * \since 0.20 -+ */ -+class POPPLER_QT4_EXPORT LinkRendition : public Link -+{ -+ public: -+ /** -+ * Describes the possible rendition actions. -+ * -+ * \since 0.22 -+ */ -+ enum RenditionAction { -+ NoRendition, -+ PlayRendition, -+ StopRendition, -+ PauseRendition, -+ ResumeRendition -+ }; -+ -+ /** -+ * Create a new rendition link. -+ * -+ * \param linkArea the active area of the link -+ * \param rendition the media rendition object. Ownership is taken -+ * -+ * \deprecated Use the constructor that takes all parameter instead -+ */ -+ Q_DECL_DEPRECATED LinkRendition( const QRectF &linkArea, ::MediaRendition *rendition ); -+ -+ /** -+ * Create a new rendition link. -+ * -+ * \param linkArea the active area of the link -+ * \param rendition the media rendition object. Ownership is taken -+ * \param operation the numeric operation (action) (@see ::LinkRendition::RenditionOperation) -+ * \param script the java script code -+ * \param annotationReference the object reference of the screen annotation associated with this rendition action -+ * \since 0.22 -+ */ -+ LinkRendition( const QRectF &linkArea, ::MediaRendition *rendition, int operation, const QString &script, const Ref &annotationReference ); -+ -+ /** -+ * Destructor. -+ */ -+ virtual ~LinkRendition(); -+ -+ LinkType linkType() const; -+ -+ /** -+ * Returns the media rendition object if the redition provides one, @c 0 otherwise -+ */ -+ MediaRendition *rendition() const; -+ -+ /** -+ * Returns the action that should be executed if a rendition object is provided. -+ * -+ * \since 0.22 -+ */ -+ RenditionAction action() const; -+ -+ /** -+ * The JS code that shall be executed or an empty string. -+ * -+ * \since 0.22 -+ */ -+ QString script() const; -+ -+ /** -+ * Returns whether the given @p annotation is the referenced screen annotation for this rendition @p link. -+ * -+ * \since 0.22 -+ */ -+ bool isReferencedAnnotation( const ScreenAnnotation *annotation ) const; -+ -+ private: -+ Q_DECLARE_PRIVATE( LinkRendition ) -+ Q_DISABLE_COPY( LinkRendition ) -+}; -+ -+/** -+ * JavaScript: a JavaScript code to be interpreted. -+ * -+ * \since 0.10 -+ */ -+class POPPLER_QT4_EXPORT LinkJavaScript : public Link -+{ -+ public: -+ /** -+ * Create a new JavaScript link. -+ * -+ * \param linkArea the active area of the link -+ * \param js the JS code to be interpreted -+ */ -+ LinkJavaScript( const QRectF &linkArea, const QString &js ); -+ /** -+ * Destructor. -+ */ -+ virtual ~LinkJavaScript(); -+ -+ LinkType linkType() const; -+ -+ /** -+ * The JS code -+ */ -+ QString script() const; -+ -+ private: -+ Q_DECLARE_PRIVATE( LinkJavaScript ) -+ Q_DISABLE_COPY( LinkJavaScript ) -+}; -+ -+/** -+ * Movie: a movie to be played. -+ * -+ * \since 0.20 -+ */ -+class POPPLER_QT4_EXPORT LinkMovie : public Link -+{ -+ public: -+ /** -+ * Describes the operation to be performed on the movie. -+ */ -+ enum Operation { Play, -+ Stop, -+ Pause, -+ Resume -+ }; -+ -+ /** -+ * Create a new Movie link. -+ * -+ * \param linkArea the active area of the link -+ * \param operation the operation to be performed on the movie -+ * \param annotationTitle the title of the movie annotation identifying the movie to be played -+ * \param annotationReference the object reference of the movie annotation identifying the movie to be played -+ * -+ * Note: This constructor is supposed to be used by Poppler::Page only. -+ */ -+ LinkMovie( const QRectF &linkArea, Operation operation, const QString &annotationTitle, const Ref &annotationReference ); -+ /** -+ * Destructor. -+ */ -+ ~LinkMovie(); -+ LinkType linkType() const; -+ /** -+ * Returns the operation to be performed on the movie. -+ */ -+ Operation operation() const; -+ /** -+ * Returns whether the given @p annotation is the referenced movie annotation for this movie @p link. -+ */ -+ bool isReferencedAnnotation( const MovieAnnotation *annotation ) const; -+ -+ private: -+ Q_DECLARE_PRIVATE( LinkMovie ) -+ Q_DISABLE_COPY( LinkMovie ) -+}; -+ -+/** -+ * OCGState: an optional content group state change. -+ * -+ * \since 0.50 -+ */ -+class POPPLER_QT4_EXPORT LinkOCGState : public Link -+{ -+ public: -+ /** -+ * Create a new OCGState link. This is only used by Poppler::Page. -+ */ -+ LinkOCGState( LinkOCGStatePrivate *ocgp ); -+ /** -+ * Destructor. -+ */ -+ ~LinkOCGState(); -+ -+ LinkType linkType() const; -+ -+ private: -+ Q_DECLARE_PRIVATE( LinkOCGState ) -+ Q_DISABLE_COPY( LinkOCGState ) -+}; -+ -+} -+ -+#endif -diff --git a/qt4/src/poppler-media.cc b/qt4/src/poppler-media.cc -new file mode 100644 -index 00000000..f385f02e ---- /dev/null -+++ b/qt4/src/poppler-media.cc -@@ -0,0 +1,168 @@ -+/* poppler-media.cc: qt interface to poppler -+ * Copyright (C) 2012 Guillermo A. Amaral B. -+ * Copyright (C) 2013 Albert Astals Cid -+ * -+ * 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-media.h" -+ -+#include "Rendition.h" -+ -+#include "poppler-private.h" -+ -+#include -+ -+#define BUFFER_MAX 4096 -+ -+namespace Poppler -+{ -+ -+class MediaRenditionPrivate -+{ -+public: -+ -+ MediaRenditionPrivate(::MediaRendition *rendition) -+ : rendition(rendition) -+ { -+ } -+ -+ ~MediaRenditionPrivate() -+ { -+ delete rendition; -+ } -+ -+ ::MediaRendition *rendition; -+}; -+ -+MediaRendition::MediaRendition(::MediaRendition *rendition) -+ : d_ptr(new MediaRenditionPrivate(rendition)) -+{ -+} -+ -+MediaRendition::~MediaRendition() -+{ -+ delete d_ptr; -+} -+ -+bool -+MediaRendition::isValid() const -+{ -+ Q_D( const MediaRendition ); -+ return d->rendition && d->rendition->isOk(); -+} -+ -+QString -+MediaRendition::contentType() const -+{ -+ Q_ASSERT(isValid() && "Invalid media rendition."); -+ Q_D( const MediaRendition ); -+ return UnicodeParsedString(d->rendition->getContentType()); -+} -+ -+QString -+MediaRendition::fileName() const -+{ -+ Q_ASSERT(isValid() && "Invalid media rendition."); -+ Q_D( const MediaRendition ); -+ return UnicodeParsedString(d->rendition->getFileName()); -+} -+ -+bool -+MediaRendition::isEmbedded() const -+{ -+ Q_ASSERT(isValid() && "Invalid media rendition."); -+ Q_D( const MediaRendition ); -+ return d->rendition->getIsEmbedded(); -+} -+ -+QByteArray -+MediaRendition::data() const -+{ -+ Q_ASSERT(isValid() && "Invalid media rendition."); -+ Q_D( const MediaRendition ); -+ -+ Stream *s = d->rendition->getEmbbededStream(); -+ if (!s) -+ return QByteArray(); -+ -+ QBuffer buffer; -+ unsigned char data[BUFFER_MAX]; -+ int bread; -+ -+ buffer.open(QIODevice::WriteOnly); -+ s->reset(); -+ while ((bread = s->doGetChars(BUFFER_MAX, data)) != 0) -+ buffer.write(reinterpret_cast(data), bread); -+ buffer.close(); -+ -+ return buffer.data(); -+} -+ -+bool -+MediaRendition::autoPlay() const -+{ -+ Q_D( const MediaRendition ); -+ if (d->rendition->getBEParameters()) { -+ return d->rendition->getBEParameters()->autoPlay; -+ } else if (d->rendition->getMHParameters()) { -+ return d->rendition->getMHParameters()->autoPlay; -+ } else qDebug("No BE or MH parameters to reference!"); -+ return false; -+} -+ -+bool -+MediaRendition::showControls() const -+{ -+ Q_D( const MediaRendition ); -+ if (d->rendition->getBEParameters()) { -+ return d->rendition->getBEParameters()->showControls; -+ } else if (d->rendition->getMHParameters()) { -+ return d->rendition->getMHParameters()->showControls; -+ } else qDebug("No BE or MH parameters to reference!"); -+ return false; -+} -+ -+float -+MediaRendition::repeatCount() const -+{ -+ Q_D( const MediaRendition ); -+ if (d->rendition->getBEParameters()) { -+ return d->rendition->getBEParameters()->repeatCount; -+ } else if (d->rendition->getMHParameters()) { -+ return d->rendition->getMHParameters()->repeatCount; -+ } else qDebug("No BE or MH parameters to reference!"); -+ return 1.f; -+} -+ -+QSize -+MediaRendition::size() const -+{ -+ Q_D( const MediaRendition ); -+ const MediaParameters *mp = 0; -+ -+ if (d->rendition->getBEParameters()) -+ mp = d->rendition->getBEParameters(); -+ else if (d->rendition->getMHParameters()) -+ mp = d->rendition->getMHParameters(); -+ else qDebug("No BE or MH parameters to reference!"); -+ -+ if (mp) -+ return QSize(mp->windowParams.width, mp->windowParams.height); -+ return QSize(); -+} -+ -+} -+ -diff --git a/qt4/src/poppler-media.h b/qt4/src/poppler-media.h -new file mode 100644 -index 00000000..34e5c361 ---- /dev/null -+++ b/qt4/src/poppler-media.h -@@ -0,0 +1,100 @@ -+/* poppler-media.h: qt interface to poppler -+ * Copyright (C) 2012 Guillermo A. Amaral B. -+ * Copyright (C) 2012, 2013 Albert Astals Cid -+ * -+ * 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_MEDIARENDITION_H__ -+#define __POPPLER_MEDIARENDITION_H__ -+ -+#include "poppler-export.h" -+ -+#include -+#include -+ -+class MediaRendition; -+class QIODevice; -+ -+namespace Poppler -+{ -+ class MediaRenditionPrivate; -+ -+ /** -+ Qt wrapper for MediaRendition. -+ -+ \since 0.20 -+ */ -+ class POPPLER_QT4_EXPORT MediaRendition { -+ public: -+ /** -+ Constructs a MediaRendition. Takes ownership of the passed rendition -+ */ -+ MediaRendition(::MediaRendition *rendition); -+ ~MediaRendition(); -+ -+ /** -+ Check if wrapper is holding a valid rendition object. -+ */ -+ bool isValid() const; -+ -+ /** -+ Returns content type. -+ */ -+ QString contentType() const; -+ -+ /** -+ Returns file name. -+ */ -+ QString fileName() const; -+ -+ /** -+ Returns true if media is embedded. -+ */ -+ bool isEmbedded() const; -+ -+ /** -+ Returns data buffer. -+ */ -+ QByteArray data() const; -+ -+ /** -+ Convenience accessor for auto-play parameter. -+ */ -+ bool autoPlay() const; -+ -+ /** -+ Convenience accessor for show controls parameter. -+ */ -+ bool showControls() const; -+ -+ /** -+ Convenience accessor for repeat count parameter. -+ */ -+ float repeatCount() const; -+ -+ /** -+ Convenience accessor for size parameter. -+ */ -+ QSize size() const; -+ -+ private: -+ Q_DECLARE_PRIVATE( MediaRendition ) -+ MediaRenditionPrivate *d_ptr; -+ Q_DISABLE_COPY( MediaRendition ) -+ }; -+} -+ -+#endif /* __POPPLER_MEDIARENDITION_H__ */ -diff --git a/qt4/src/poppler-movie.cc b/qt4/src/poppler-movie.cc -new file mode 100644 -index 00000000..a64847c0 ---- /dev/null -+++ b/qt4/src/poppler-movie.cc -@@ -0,0 +1,110 @@ -+/* poppler-sound.cc: qt interface to poppler -+ * Copyright (C) 2008, 2010, Pino Toscano -+ * Copyright (C) 2008, Albert Astals Cid -+ * Copyright (C) 2010, Carlos Garcia Campos -+ * Copyright (C) 2012, Tobias Koenig -+ * -+ * 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-qt4.h" -+ -+#include "Object.h" -+#include "Annot.h" -+#include "Movie.h" -+ -+#include -+ -+namespace Poppler -+{ -+ -+class MovieData -+{ -+public: -+ MovieData() -+ : m_movieObj( 0 ) -+ { -+ } -+ -+ ~MovieData() -+ { -+ delete m_movieObj; -+ } -+ -+ Movie *m_movieObj; -+ QSize m_size; -+ int m_rotation; -+ QImage m_posterImage; -+ MovieObject::PlayMode m_playMode : 3; -+ bool m_showControls : 1; -+}; -+ -+MovieObject::MovieObject( AnnotMovie *ann ) -+{ -+ m_movieData = new MovieData(); -+ m_movieData->m_movieObj = ann->getMovie()->copy(); -+ //TODO: copy poster image -+ -+ MovieActivationParameters *mp = m_movieData->m_movieObj->getActivationParameters(); -+ int width, height; -+ m_movieData->m_movieObj->getFloatingWindowSize(&width, &height); -+ m_movieData->m_size = QSize(width, height); -+ m_movieData->m_rotation = m_movieData->m_movieObj->getRotationAngle(); -+ m_movieData->m_showControls = mp->showControls; -+ m_movieData->m_playMode = (MovieObject::PlayMode)mp->repeatMode; -+} -+ -+MovieObject::~MovieObject() -+{ -+ delete m_movieData; -+} -+ -+QString MovieObject::url() const -+{ -+ GooString * goo = m_movieData->m_movieObj->getFileName(); -+ return goo ? QString( goo->c_str() ) : QString(); -+} -+ -+QSize MovieObject::size() const -+{ -+ return m_movieData->m_size; -+} -+ -+int MovieObject::rotation() const -+{ -+ return m_movieData->m_rotation; -+} -+ -+bool MovieObject::showControls() const -+{ -+ return m_movieData->m_showControls; -+} -+ -+MovieObject::PlayMode MovieObject::playMode() const -+{ -+ return m_movieData->m_playMode; -+} -+ -+bool MovieObject::showPosterImage() const -+{ -+ return (m_movieData->m_movieObj->getShowPoster() == true); -+} -+ -+QImage MovieObject::posterImage() const -+{ -+ return m_movieData->m_posterImage; -+} -+ -+} -diff --git a/qt4/src/poppler-optcontent-private.h b/qt4/src/poppler-optcontent-private.h -new file mode 100644 -index 00000000..b5e52999 ---- /dev/null -+++ b/qt4/src/poppler-optcontent-private.h -@@ -0,0 +1,124 @@ -+/* poppler-optcontent-private.h: qt interface to poppler -+ * -+ * Copyright (C) 2007, Brad Hards -+ * Copyright (C) 2008, Pino Toscano -+ * Copyright (C) 2016, Albert Astals Cid -+ * Copyright (C) 2017, Hubert Figuière -+ * -+ * 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_OPTCONTENT_PRIVATE_H -+#define POPPLER_OPTCONTENT_PRIVATE_H -+ -+#include -+#include -+#include -+ -+class Array; -+class OCGs; -+class OptionalContentGroup; -+ -+class QModelIndex; -+ -+namespace Poppler -+{ -+ class OptContentItem; -+ class OptContentModel; -+ class OptContentModelPrivate; -+ -+ class RadioButtonGroup -+ { -+ public: -+ RadioButtonGroup( OptContentModelPrivate *ocModel, Array *rbarray); -+ ~RadioButtonGroup(); -+ QSet setItemOn( OptContentItem *itemToSetOn ); -+ -+ private: -+ QList itemsInGroup; -+ }; -+ -+ class OptContentItem -+ { -+ public: -+ enum ItemState { On, Off, HeadingOnly }; -+ -+ OptContentItem( OptionalContentGroup *group ); -+ OptContentItem( const QString &label ); -+ OptContentItem(); -+ ~OptContentItem(); -+ -+ QString name() const { return m_name; } -+ ItemState state() const { return m_stateBackup; } -+ void setState(ItemState state, bool obeyRadioGroups, QSet &changedItems); -+ -+ QList childList() { return m_children; } -+ -+ void setParent( OptContentItem* parent) { m_parent = parent; } -+ OptContentItem* parent() { return m_parent; } -+ -+ void addChild( OptContentItem *child ); -+ -+ void appendRBGroup( RadioButtonGroup *rbgroup ); -+ -+ bool isEnabled() const { return m_enabled; } -+ -+ QSet recurseListChildren(bool includeMe = false) const; -+ -+ private: -+ OptionalContentGroup *m_group; -+ QString m_name; -+ ItemState m_state; // true for ON, false for OFF -+ ItemState m_stateBackup; -+ QList m_children; -+ OptContentItem *m_parent; -+ QList m_rbGroups; -+ bool m_enabled; -+ }; -+ -+ class OptContentModelPrivate -+ { -+ public: -+ OptContentModelPrivate( OptContentModel *qq, OCGs *optContent ); -+ ~OptContentModelPrivate(); -+ -+ void parseRBGroupsArray( Array *rBGroupArray ); -+ OptContentItem *nodeFromIndex(const QModelIndex &index, bool canBeNull = false) const; -+ QModelIndex indexFromItem(OptContentItem *node, int column) const; -+ -+ /** -+ Get the OptContentItem corresponding to a given reference value. -+ -+ \param ref the reference number (e.g. from Object.getRefNum()) to look up -+ -+ \return the matching optional content item, or null if the reference wasn't found -+ */ -+ OptContentItem *itemFromRef( const QString &ref ) const; -+ void setRootNode(OptContentItem *node); -+ -+ OptContentModel *q; -+ -+ QMap m_optContentItems; -+ QList m_headerOptContentItems; -+ QList m_rbgroups; -+ OptContentItem *m_rootNode; -+ -+ private: -+ void addChild( OptContentItem *parent, OptContentItem *child); -+ void parseOrderArray( OptContentItem *parentNode, Array *orderArray ); -+ }; -+} -+ -+#endif -diff --git a/qt4/src/poppler-optcontent.cc b/qt4/src/poppler-optcontent.cc -new file mode 100644 -index 00000000..0e7b5345 ---- /dev/null -+++ b/qt4/src/poppler-optcontent.cc -@@ -0,0 +1,455 @@ -+/* poppler-optcontent.cc: qt interface to poppler -+ * -+ * Copyright (C) 2007, Brad Hards -+ * Copyright (C) 2008, 2014, Pino Toscano -+ * Copyright (C) 2008, Carlos Garcia Campos -+ * Copyright (C) 2015-2017, Albert Astals Cid -+ * Copyright (C) 2017, Hubert Figuière -+ * -+ * 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-optcontent.h" -+ -+#include "poppler-optcontent-private.h" -+ -+#include "poppler-private.h" -+#include "poppler-link-private.h" -+ -+#include -+#include -+ -+#include "poppler/OptionalContent.h" -+#include "poppler/Link.h" -+ -+namespace Poppler -+{ -+ -+ RadioButtonGroup::RadioButtonGroup( OptContentModelPrivate *ocModel, Array *rbarray ) -+ { -+ itemsInGroup.reserve( rbarray->getLength() ); -+ for (int i = 0; i < rbarray->getLength(); ++i) { -+ const Object &ref = rbarray->getNF( i ); -+ if ( ! ref.isRef() ) { -+ qDebug() << "expected ref, but got:" << ref.getType(); -+ } -+ OptContentItem *item = ocModel->itemFromRef( QString::number(ref.getRefNum() ) ); -+ itemsInGroup.append( item ); -+ } -+ for (int i = 0; i < itemsInGroup.size(); ++i) { -+ OptContentItem *item = itemsInGroup.at(i); -+ item->appendRBGroup( this ); -+ } -+ } -+ -+ RadioButtonGroup::~RadioButtonGroup() -+ { -+ } -+ -+ QSet RadioButtonGroup::setItemOn( OptContentItem *itemToSetOn ) -+ { -+ QSet changedItems; -+ for (int i = 0; i < itemsInGroup.size(); ++i) { -+ OptContentItem *thisItem = itemsInGroup.at(i); -+ if (thisItem != itemToSetOn) { -+ QSet newChangedItems; -+ thisItem->setState(OptContentItem::Off, false /*obeyRadioGroups*/, newChangedItems); -+ changedItems += newChangedItems; -+ } -+ } -+ return changedItems; -+ } -+ -+ -+ -+ OptContentItem::OptContentItem( OptionalContentGroup *group ) -+ { -+ m_group = group; -+ m_parent = 0; -+ m_name = UnicodeParsedString( group->getName() ); -+ if ( group->getState() == OptionalContentGroup::On ) { -+ m_state = OptContentItem::On; -+ } else { -+ m_state = OptContentItem::Off; -+ } -+ m_stateBackup = m_state; -+ m_enabled = true; -+ } -+ -+ OptContentItem::OptContentItem( const QString &label ) -+ { -+ m_parent = 0; -+ m_name = label; -+ m_group = 0; -+ m_state = OptContentItem::HeadingOnly; -+ m_stateBackup = m_state; -+ m_enabled = true; -+ } -+ -+ OptContentItem::OptContentItem() : -+ m_parent( 0 ), m_enabled(true) -+ { -+ } -+ -+ OptContentItem::~OptContentItem() -+ { -+ } -+ -+ void OptContentItem::appendRBGroup( RadioButtonGroup *rbgroup ) -+ { -+ m_rbGroups.append( rbgroup ); -+ } -+ -+ -+ void OptContentItem::setState(ItemState state, bool obeyRadioGroups, QSet &changedItems) -+ { -+ if (state == m_state) -+ return; -+ -+ m_state = state; -+ m_stateBackup = m_state; -+ changedItems.insert(this); -+ QSet empty; -+ Q_FOREACH (OptContentItem *child, m_children) { -+ ItemState oldState = child->m_stateBackup; -+ child->setState(state == OptContentItem::On ? child->m_stateBackup : OptContentItem::Off, true /*obeyRadioGroups*/, empty); -+ child->m_enabled = state == OptContentItem::On; -+ child->m_stateBackup = oldState; -+ } -+ if (!m_group || !obeyRadioGroups) { -+ return; -+ } -+ if ( state == OptContentItem::On ) { -+ m_group->setState( OptionalContentGroup::On ); -+ for (int i = 0; i < m_rbGroups.size(); ++i) { -+ RadioButtonGroup *rbgroup = m_rbGroups.at(i); -+ changedItems += rbgroup->setItemOn( this ); -+ } -+ } else if ( state == OptContentItem::Off ) { -+ m_group->setState( OptionalContentGroup::Off ); -+ } -+ } -+ -+ void OptContentItem::addChild( OptContentItem *child ) -+ { -+ m_children += child; -+ child->setParent( this ); -+ } -+ -+ QSet OptContentItem::recurseListChildren(bool includeMe) const -+ { -+ QSet ret; -+ if (includeMe) { -+ ret.insert(const_cast(this)); -+ } -+ Q_FOREACH (OptContentItem *child, m_children) { -+ ret += child->recurseListChildren(true); -+ } -+ return ret; -+ } -+ -+ OptContentModelPrivate::OptContentModelPrivate( OptContentModel *qq, OCGs *optContent ) -+ : q(qq) -+ { -+ m_rootNode = new OptContentItem(); -+ const auto &ocgs = optContent->getOCGs(); -+ -+ for (const auto& ocg : ocgs) { -+ OptContentItem *node = new OptContentItem( ocg.second.get() ); -+ m_optContentItems.insert( QString::number( ocg.first.num ), node ); -+ } -+ -+ if ( optContent->getOrderArray() == 0 ) { -+ // no Order array, so drop them all at the top level -+ QMapIterator i(m_optContentItems); -+ while ( i.hasNext() ) { -+ i.next(); -+ addChild( m_rootNode, i.value() ); -+ } -+ } else { -+ parseOrderArray( m_rootNode, optContent->getOrderArray() ); -+ } -+ -+ parseRBGroupsArray( optContent->getRBGroupsArray() ); -+ } -+ -+ OptContentModelPrivate::~OptContentModelPrivate() -+ { -+ qDeleteAll( m_optContentItems ); -+ qDeleteAll( m_rbgroups ); -+ qDeleteAll( m_headerOptContentItems ); -+ delete m_rootNode; -+ } -+ -+ void OptContentModelPrivate::parseOrderArray( OptContentItem *parentNode, Array *orderArray ) -+ { -+ OptContentItem *lastItem = parentNode; -+ for (int i = 0; i < orderArray->getLength(); ++i) { -+ Object orderItem = orderArray->get(i); -+ if ( orderItem.isDict() ) { -+ const Object &item = orderArray->getNF(i); -+ if (item.isRef() ) { -+ OptContentItem *ocItem = m_optContentItems.value(QString::number(item.getRefNum()), 0); -+ if (ocItem) { -+ addChild( parentNode, ocItem ); -+ lastItem = ocItem; -+ } else { -+ qDebug() << "could not find group for object" << item.getRefNum(); -+ } -+ } -+ } else if ( (orderItem.isArray()) && (orderItem.arrayGetLength() > 0) ) { -+ parseOrderArray(lastItem, orderItem.getArray()); -+ } else if ( orderItem.isString() ) { -+ const GooString *label = orderItem.getString(); -+ OptContentItem *header = new OptContentItem ( UnicodeParsedString ( label ) ); -+ m_headerOptContentItems.append( header ); -+ addChild( parentNode, header ); -+ parentNode = header; -+ lastItem = header; -+ } else { -+ qDebug() << "something unexpected"; -+ } -+ } -+ } -+ -+ void OptContentModelPrivate::parseRBGroupsArray( Array *rBGroupArray ) -+ { -+ if (! rBGroupArray) { -+ return; -+ } -+ // This is an array of array(s) -+ for (int i = 0; i < rBGroupArray->getLength(); ++i) { -+ Object rbObj = rBGroupArray->get(i); -+ if ( ! rbObj.isArray() ) { -+ qDebug() << "expected inner array, got:" << rbObj.getType(); -+ return; -+ } -+ Array *rbarray = rbObj.getArray(); -+ RadioButtonGroup *rbg = new RadioButtonGroup( this, rbarray ); -+ m_rbgroups.append( rbg ); -+ } -+ } -+ -+ OptContentModel::OptContentModel( OCGs *optContent, QObject *parent) -+ : QAbstractItemModel(parent) -+ { -+ d = new OptContentModelPrivate( this, optContent ); -+ } -+ -+ OptContentModel::~OptContentModel() -+ { -+ delete d; -+ } -+ -+ void OptContentModelPrivate::setRootNode(OptContentItem *node) -+ { -+ delete m_rootNode; -+ m_rootNode = node; -+ q->reset(); -+ } -+ -+ QModelIndex OptContentModel::index(int row, int column, const QModelIndex &parent) const -+ { -+ if (row < 0 || column != 0) { -+ return QModelIndex(); -+ } -+ -+ OptContentItem *parentNode = d->nodeFromIndex( parent ); -+ if (row < parentNode->childList().count()) { -+ return createIndex(row, column, parentNode->childList().at(row)); -+ } -+ return QModelIndex(); -+ } -+ -+ QModelIndex OptContentModel::parent(const QModelIndex &child) const -+ { -+ OptContentItem *childNode = d->nodeFromIndex( child ); -+ if (!childNode) { -+ return QModelIndex(); -+ } -+ return d->indexFromItem(childNode->parent(), child.column()); -+ } -+ -+ QModelIndex OptContentModelPrivate::indexFromItem(OptContentItem *node, int column) const -+ { -+ if (!node) { -+ return QModelIndex(); -+ } -+ OptContentItem *parentNode = node->parent(); -+ if (!parentNode) { -+ return QModelIndex(); -+ } -+ const int row = parentNode->childList().indexOf(node); -+ return q->createIndex(row, column, node); -+ } -+ -+ int OptContentModel::rowCount(const QModelIndex &parent) const -+ { -+ OptContentItem *parentNode = d->nodeFromIndex( parent ); -+ if (!parentNode) { -+ return 0; -+ } else { -+ return parentNode->childList().count(); -+ } -+ } -+ -+ int OptContentModel::columnCount(const QModelIndex &parent) const -+ { -+ return 1; -+ } -+ -+ -+ QVariant OptContentModel::data(const QModelIndex &index, int role) const -+ { -+ OptContentItem *node = d->nodeFromIndex(index, true); -+ if (!node) { -+ return QVariant(); -+ } -+ -+ switch (role) { -+ case Qt::DisplayRole: -+ return node->name(); -+ break; -+ case Qt::EditRole: -+ if (node->state() == OptContentItem::On) { -+ return true; -+ } else if (node->state() == OptContentItem::Off) { -+ return false; -+ } -+ break; -+ case Qt::CheckStateRole: -+ if (node->state() == OptContentItem::On) { -+ return Qt::Checked; -+ } else if (node->state() == OptContentItem::Off) { -+ return Qt::Unchecked; -+ } -+ break; -+ } -+ -+ return QVariant(); -+ } -+ -+ bool OptContentModel::setData ( const QModelIndex & index, const QVariant & value, int role ) -+ { -+ OptContentItem *node = d->nodeFromIndex(index, true); -+ if (!node) { -+ return false; -+ } -+ -+ switch (role) { -+ case Qt::CheckStateRole: -+ { -+ const bool newvalue = value.toBool(); -+ QSet changedItems; -+ node->setState(newvalue ? OptContentItem::On : OptContentItem::Off, true /*obeyRadioGroups*/, changedItems); -+ -+ if (!changedItems.isEmpty()) { -+ changedItems += node->recurseListChildren(false); -+ QModelIndexList indexes; -+ Q_FOREACH (OptContentItem *item, changedItems) { -+ indexes.append(d->indexFromItem(item, 0)); -+ } -+ qStableSort(indexes); -+ Q_FOREACH (const QModelIndex &changedIndex, indexes) { -+ emit dataChanged(changedIndex, changedIndex); -+ } -+ return true; -+ } -+ break; -+ } -+ } -+ -+ return false; -+ } -+ -+ Qt::ItemFlags OptContentModel::flags ( const QModelIndex & index ) const -+ { -+ OptContentItem *node = d->nodeFromIndex(index); -+ Qt::ItemFlags itemFlags = Qt::ItemIsSelectable | Qt::ItemIsUserCheckable; -+ if (node->isEnabled()) { -+ itemFlags |= Qt::ItemIsEnabled; -+ } -+ return itemFlags; -+ } -+ -+ QVariant OptContentModel::headerData( int section, Qt::Orientation orientation, int role ) const -+ { -+ return QAbstractItemModel::headerData( section, orientation, role ); -+ } -+ -+ void OptContentModel::applyLink( LinkOCGState *link ) -+ { -+ ::LinkOCGState *popplerLinkOCGState = static_cast(link->d_ptr)->popplerLinkOCGState; -+ -+ QSet changedItems; -+ -+ const std::vector<::LinkOCGState::StateList>& statesList = popplerLinkOCGState->getStateList(); -+ for (const ::LinkOCGState::StateList& stateList : statesList) { -+ const std::vector& refsList = stateList.list; -+ for (const Ref& ref : refsList) { -+ OptContentItem *item = d->itemFromRef(QString::number(ref.num)); -+ -+ -+ -+ -+ if (stateList.st == ::LinkOCGState::On) { -+ item->setState(OptContentItem::On, popplerLinkOCGState->getPreserveRB(), changedItems); -+ } else if (stateList.st == ::LinkOCGState::Off) { -+ item->setState(OptContentItem::Off, popplerLinkOCGState->getPreserveRB(), changedItems); -+ } else { -+ OptContentItem::ItemState newState = item->state() == OptContentItem::On ? OptContentItem::Off : OptContentItem::On; -+ item->setState(newState, popplerLinkOCGState->getPreserveRB(), changedItems); -+ } -+ } -+ } -+ -+ if (!changedItems.isEmpty()) { -+ QSet aux; -+ Q_FOREACH (OptContentItem *item, aux) { -+ changedItems += item->recurseListChildren(false); -+ } -+ -+ QModelIndexList indexes; -+ Q_FOREACH (OptContentItem *item, changedItems) { -+ indexes.append(d->indexFromItem(item, 0)); -+ } -+ qStableSort(indexes); -+ Q_FOREACH (const QModelIndex &changedIndex, indexes) { -+ emit dataChanged(changedIndex, changedIndex); -+ } -+ } -+ } -+ -+ void OptContentModelPrivate::addChild( OptContentItem *parent, OptContentItem *child ) -+ { -+ parent->addChild( child ); -+ } -+ -+ OptContentItem* OptContentModelPrivate::itemFromRef( const QString &ref ) const -+ { -+ return m_optContentItems.value(ref, 0); -+ } -+ -+ OptContentItem* OptContentModelPrivate::nodeFromIndex(const QModelIndex &index, bool canBeNull) const -+ { -+ if (index.isValid()) { -+ return static_cast(index.internalPointer()); -+ } else { -+ return canBeNull ? 0 : m_rootNode; -+ } -+ } -+} -+ -+#include "poppler-optcontent.moc" -diff --git a/qt4/src/poppler-optcontent.h b/qt4/src/poppler-optcontent.h -new file mode 100644 -index 00000000..bf00a88d ---- /dev/null -+++ b/qt4/src/poppler-optcontent.h -@@ -0,0 +1,84 @@ -+/* poppler-optcontent.h: qt interface to poppler -+ * -+ * Copyright (C) 2007, Brad Hards -+ * Copyright (C) 2008, Pino Toscano -+ * Copyright (C) 2016, Albert Astals Cid -+ * -+ * 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_OPTCONTENT_H -+#define POPPLER_OPTCONTENT_H -+ -+#include -+ -+#include "poppler-export.h" -+#include "poppler-link.h" -+ -+class OCGs; -+ -+namespace Poppler -+{ -+ class Document; -+ class OptContentModelPrivate; -+ -+ /** -+ * \brief Model for optional content -+ * -+ * OptContentModel is an item model representing the optional content items -+ * that can be found in PDF documents. -+ * -+ * The model offers a mostly read-only display of the data, allowing to -+ * enable/disable some contents setting the Qt::CheckStateRole data role. -+ * -+ * \since 0.8 -+ */ -+ class POPPLER_QT4_EXPORT OptContentModel : public QAbstractItemModel -+ { -+ friend class Document; -+ -+ Q_OBJECT -+ -+ public: -+ virtual ~OptContentModel(); -+ -+ QModelIndex index(int row, int column, const QModelIndex &parent) const; -+ QModelIndex parent(const QModelIndex &child) const; -+ -+ int rowCount(const QModelIndex &parent = QModelIndex()) const; -+ int columnCount(const QModelIndex &parent) const; -+ -+ QVariant data(const QModelIndex &index, int role) const; -+ virtual bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); -+ -+ Qt::ItemFlags flags ( const QModelIndex & index ) const; -+ -+ virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; -+ -+ /** -+ * Applies the Optional Content Changes specified by that link. -+ * \since 0.50 -+ */ -+ void applyLink( LinkOCGState *link ); -+ -+ private: -+ OptContentModel( OCGs *optContent, QObject *parent = 0); -+ -+ friend class OptContentModelPrivate; -+ OptContentModelPrivate *d; -+ }; -+} -+ -+#endif -diff --git a/qt4/src/poppler-page-private.h b/qt4/src/poppler-page-private.h -new file mode 100644 -index 00000000..1cb63e9f ---- /dev/null -+++ b/qt4/src/poppler-page-private.h -@@ -0,0 +1,57 @@ -+/* poppler-page.cc: qt interface to poppler -+ * Copyright (C) 2005, Net Integration Technologies, Inc. -+ * Copyright (C) 2007, 2012, Albert Astals Cid -+ * Copyright (C) 2008, Pino Toscano -+ * Copyright (C) 2015 Adam Reichold -+ * -+ * 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_PAGE_PRIVATE_H_ -+#define _POPPLER_PAGE_PRIVATE_H_ -+ -+#include "CharTypes.h" -+ -+class QRectF; -+ -+class LinkAction; -+class Page; -+class TextPage; -+ -+namespace Poppler -+{ -+ -+class DocumentData; -+class PageTransition; -+ -+class PageData { -+public: -+ Link* convertLinkActionToLink(::LinkAction * a, const QRectF &linkArea); -+ -+ DocumentData *parentDoc; -+ ::Page *page; -+ int index; -+ PageTransition *transition; -+ -+ static Link* convertLinkActionToLink(::LinkAction * a, DocumentData *parentDoc, const QRectF &linkArea); -+ -+ TextPage *prepareTextSearch(const QString &text, Page::Rotation rotate, QVector *u); -+ bool performSingleTextSearch(TextPage* textPage, QVector &u, double &sLeft, double &sTop, double &sRight, double &sBottom, Page::SearchDirection direction, bool sCase, bool sWords); -+ QList performMultipleTextSearch(TextPage* textPage, QVector &u, bool sCase, bool sWords); -+}; -+ -+} -+ -+#endif -diff --git a/qt4/src/poppler-page-transition-private.h b/qt4/src/poppler-page-transition-private.h -new file mode 100644 -index 00000000..63febb09 ---- /dev/null -+++ b/qt4/src/poppler-page-transition-private.h -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2005, Albert Astals Cid -+ * -+ * 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. -+ */ -+ -+class Object; -+ -+namespace Poppler { -+ -+class PageTransitionParams { -+ public: -+ Object *dictObj; -+}; -+ -+} -diff --git a/qt4/src/poppler-page-transition.cc b/qt4/src/poppler-page-transition.cc -new file mode 100644 -index 00000000..4fa39edd ---- /dev/null -+++ b/qt4/src/poppler-page-transition.cc -@@ -0,0 +1,101 @@ -+/* PageTransition.cc -+ * Copyright (C) 2005, Net Integration Technologies, Inc. -+ * Copyright (C) 2015, Arseniy Lartsev -+ * -+ * 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 "PageTransition.h" -+#include "poppler-page-transition.h" -+#include "poppler-page-transition-private.h" -+ -+namespace Poppler { -+ -+class PageTransitionData -+{ -+ public: -+ PageTransitionData(Object *trans) -+ { -+ pt = new ::PageTransition(trans); -+ } -+ -+ PageTransitionData(const PageTransitionData &ptd) -+ { -+ pt = new ::PageTransition(*ptd.pt); -+ } -+ -+ ~PageTransitionData() -+ { -+ delete pt; -+ } -+ -+ ::PageTransition *pt; -+}; -+ -+PageTransition::PageTransition(const PageTransitionParams ¶ms) -+{ -+ data = new PageTransitionData(params.dictObj); -+} -+ -+PageTransition::PageTransition(const PageTransition &pt) -+{ -+ data = new PageTransitionData(*pt.data); -+} -+ -+PageTransition::~PageTransition() -+{ -+ delete data; -+} -+ -+PageTransition::Type PageTransition::type() const -+{ -+ return (Poppler::PageTransition::Type)data->pt->getType(); -+} -+ -+int PageTransition::duration() const -+{ -+ return data->pt->getDuration(); -+} -+ -+double PageTransition::durationReal() const -+{ -+ return data->pt->getDuration(); -+} -+ -+PageTransition::Alignment PageTransition::alignment() const -+{ -+ return (Poppler::PageTransition::Alignment)data->pt->getAlignment(); -+} -+ -+PageTransition::Direction PageTransition::direction() const -+{ -+ return (Poppler::PageTransition::Direction)data->pt->getDirection(); -+} -+ -+int PageTransition::angle() const -+{ -+ return data->pt->getAngle(); -+} -+ -+double PageTransition::scale() const -+{ -+ return data->pt->getScale(); -+} -+bool PageTransition::isRectangular() const -+{ -+ return data->pt->isRectangular(); -+} -+ -+} -diff --git a/qt4/src/poppler-page-transition.h b/qt4/src/poppler-page-transition.h -new file mode 100644 -index 00000000..e92adbd8 ---- /dev/null -+++ b/qt4/src/poppler-page-transition.h -@@ -0,0 +1,158 @@ -+/* PageTransition.h -+ * Copyright (C) 2005, Net Integration Technologies, Inc. -+ * Copyright (C) 2005, Brad Hards -+ * Copyright (C) 2015, Arseniy Lartsev -+ * -+ * 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 __PAGETRANSITION_X_H__ -+#define __PAGETRANSITION_X_H__ -+ -+#include "poppler-export.h" -+ -+#include -+ -+namespace Poppler { -+ -+class PageTransitionParams; -+class PageTransitionData; -+ -+/** -+ \brief Describes how a PDF file viewer shall perform the transition -+ from one page to another -+ -+ In PDF files there is a way to specify if the viewer shall use -+ certain effects to perform the transition from one page to -+ another. This feature can be used, e.g., in a PDF-based beamer -+ presentation. -+ -+ This utility class represents the transition effect, and can be -+ used to extract the information from a PDF object. -+*/ -+ -+ -+class POPPLER_QT4_EXPORT PageTransition { -+ public: -+ -+ /** \brief transition effect that shall be used -+ */ -+ // if changed remember to keep in sync with PageTransition.h enum -+ enum Type { -+ Replace = 0, -+ Split, -+ Blinds, -+ Box, -+ Wipe, -+ Dissolve, -+ Glitter, -+ Fly, -+ Push, -+ Cover, -+ Uncover, -+ Fade -+ }; -+ -+ /** \brief alignment of the transition effect that shall be used -+ */ -+ // if changed remember to keep in sync with PageTransition.h enum -+ enum Alignment { -+ Horizontal = 0, -+ Vertical -+ }; -+ -+ /** \brief direction of the transition effect that shall be used -+ */ -+ // if changed remember to keep in sync with PageTransition.h enum -+ enum Direction { -+ Inward = 0, -+ Outward -+ }; -+ -+ /** \brief Construct a new PageTransition object from a page dictionary. -+ -+ Users of the library will rarely need to construct a -+ PageTransition object themselves. Instead, the method -+ Poppler::Page::transition() can be used to find out if a certain -+ transition effect is specified. -+ -+ @warning In case or error, this method will print an error message to stderr, -+ and construct a default object. -+ -+ @param params an object whose dictionary will be read and -+ parsed. This must be a valid object, whose dictionaries are -+ accessed by the constructor. The object is only accessed by this -+ constructor, and may be deleted after the constructor returns. -+ */ -+ PageTransition(const PageTransitionParams ¶ms); -+ -+ /** \brief copy constructor */ -+ PageTransition(const PageTransition &pt); -+ -+ /** -+ Destructor -+ */ -+ ~PageTransition(); -+ -+ /** -+ \brief Get type of the transition. -+ */ -+ Type type() const; -+ -+ /** -+ \brief Get duration of the transition in seconds as integer -+ -+ \deprecated This function is left for backward compatibility, use durationReal() instead. -+ */ -+ Q_DECL_DEPRECATED int duration() const; -+ -+ /** -+ \brief Get duration of the transition in seconds -+ */ -+ double durationReal() const; -+ -+ /** -+ \brief Get dimension in which the transition effect occurs. -+ */ -+ Alignment alignment() const; -+ -+ /** -+ \brief Get direction of motion of the transition effect. -+ */ -+ Direction direction() const; -+ -+ /** -+ \brief Get direction in which the transition effect moves. -+ */ -+ int angle() const; -+ -+ /** -+ \brief Get starting or ending scale. -+ */ -+ double scale() const; -+ -+ /** -+ \brief Returns true if the area to be flown is rectangular and -+ opaque. -+ */ -+ bool isRectangular() const; -+ -+ private: -+ PageTransitionData *data; -+}; -+ -+} -+ -+#endif -diff --git a/qt4/src/poppler-page.cc b/qt4/src/poppler-page.cc -new file mode 100644 -index 00000000..ffe6e99c ---- /dev/null -+++ b/qt4/src/poppler-page.cc -@@ -0,0 +1,810 @@ -+/* poppler-page.cc: qt interface to poppler -+ * Copyright (C) 2005, Net Integration Technologies, Inc. -+ * Copyright (C) 2005, Brad Hards -+ * Copyright (C) 2005-2017, Albert Astals Cid -+ * Copyright (C) 2005, Stefan Kebekus -+ * Copyright (C) 2006-2011, Pino Toscano -+ * Copyright (C) 2008 Carlos Garcia Campos -+ * Copyright (C) 2009 Shawn Rutledge -+ * Copyright (C) 2010, 2012, Guillermo Amaral -+ * Copyright (C) 2010 Suzuki Toshiya -+ * Copyright (C) 2010 Matthias Fauconneau -+ * Copyright (C) 2010 Hib Eris -+ * Copyright (C) 2012 Tobias Koenig -+ * Copyright (C) 2012 Fabio D'Urso -+ * Copyright (C) 2012, 2015 Adam Reichold -+ * Copyright (C) 2012, 2013 Thomas Freitag -+ * Copyright (C) 2015 William Bader -+ * Copyright (C) 2016 Arseniy Lartsev -+ * Copyright (C) 2017 Adrian Johnson -+ * -+ * 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 -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if defined(HAVE_SPLASH) -+#include -+#include -+#endif -+ -+#include "poppler-private.h" -+#include "poppler-page-transition-private.h" -+#include "poppler-page-private.h" -+#include "poppler-link-extractor-private.h" -+#include "poppler-link-private.h" -+#include "poppler-annotation-private.h" -+#include "poppler-form.h" -+#include "poppler-media.h" -+ -+namespace Poppler { -+ -+Link* PageData::convertLinkActionToLink(::LinkAction * a, const QRectF &linkArea) -+{ -+ return convertLinkActionToLink(a, parentDoc, linkArea); -+} -+ -+Link* PageData::convertLinkActionToLink(::LinkAction * a, DocumentData *parentDoc, const QRectF &linkArea) -+{ -+ if ( !a ) -+ return NULL; -+ -+ Link * popplerLink = NULL; -+ switch ( a->getKind() ) -+ { -+ case actionGoTo: -+ { -+ LinkGoTo * g = (LinkGoTo *) a; -+ const LinkDestinationData ldd( g->getDest(), g->getNamedDest(), parentDoc, false ); -+ // create link: no ext file, namedDest, object pointer -+ popplerLink = new LinkGoto( linkArea, QString::null, LinkDestination( ldd ) ); -+ } -+ break; -+ -+ case actionGoToR: -+ { -+ LinkGoToR * g = (LinkGoToR *) a; -+ // copy link file -+ const QString fileName = UnicodeParsedString( g->getFileName() ); -+ const LinkDestinationData ldd( g->getDest(), g->getNamedDest(), parentDoc, !fileName.isEmpty() ); -+ // ceate link: fileName, namedDest, object pointer -+ popplerLink = new LinkGoto( linkArea, fileName, LinkDestination( ldd ) ); -+ } -+ break; -+ -+ case actionLaunch: -+ { -+ LinkLaunch * e = (LinkLaunch *)a; -+ const GooString * p = e->getParams(); -+ popplerLink = new LinkExecute( linkArea, e->getFileName()->c_str(), p ? p->c_str() : 0 ); -+ } -+ break; -+ -+ case actionNamed: -+ { -+ const char * name = ((LinkNamed *)a)->getName()->c_str(); -+ if ( !strcmp( name, "NextPage" ) ) -+ popplerLink = new LinkAction( linkArea, LinkAction::PageNext ); -+ else if ( !strcmp( name, "PrevPage" ) ) -+ popplerLink = new LinkAction( linkArea, LinkAction::PagePrev ); -+ else if ( !strcmp( name, "FirstPage" ) ) -+ popplerLink = new LinkAction( linkArea, LinkAction::PageFirst ); -+ else if ( !strcmp( name, "LastPage" ) ) -+ popplerLink = new LinkAction( linkArea, LinkAction::PageLast ); -+ else if ( !strcmp( name, "GoBack" ) ) -+ popplerLink = new LinkAction( linkArea, LinkAction::HistoryBack ); -+ else if ( !strcmp( name, "GoForward" ) ) -+ popplerLink = new LinkAction( linkArea, LinkAction::HistoryForward ); -+ else if ( !strcmp( name, "Quit" ) ) -+ popplerLink = new LinkAction( linkArea, LinkAction::Quit ); -+ else if ( !strcmp( name, "GoToPage" ) ) -+ popplerLink = new LinkAction( linkArea, LinkAction::GoToPage ); -+ else if ( !strcmp( name, "Find" ) ) -+ popplerLink = new LinkAction( linkArea, LinkAction::Find ); -+ else if ( !strcmp( name, "FullScreen" ) ) -+ popplerLink = new LinkAction( linkArea, LinkAction::Presentation ); -+ else if ( !strcmp( name, "Print" ) ) -+ popplerLink = new LinkAction( linkArea, LinkAction::Print ); -+ else if ( !strcmp( name, "Close" ) ) -+ { -+ // acroread closes the document always, doesnt care whether -+ // its presentation mode or not -+ // popplerLink = new LinkAction( linkArea, LinkAction::EndPresentation ); -+ popplerLink = new LinkAction( linkArea, LinkAction::Close ); -+ } -+ else -+ { -+ // TODO -+ } -+ } -+ break; -+ -+ case actionURI: -+ { -+ popplerLink = new LinkBrowse( linkArea, ((LinkURI *)a)->getURI()->c_str() ); -+ } -+ break; -+ -+ case actionSound: -+ { -+ ::LinkSound *ls = (::LinkSound *)a; -+ popplerLink = new LinkSound( linkArea, ls->getVolume(), ls->getSynchronous(), ls->getRepeat(), ls->getMix(), new SoundObject( ls->getSound() ) ); -+ } -+ break; -+ -+ case actionJavaScript: -+ { -+ ::LinkJavaScript *ljs = (::LinkJavaScript *)a; -+ popplerLink = new LinkJavaScript( linkArea, UnicodeParsedString(ljs->getScript()) ); -+ } -+ break; -+ -+ case actionMovie: -+ { -+ ::LinkMovie *lm = (::LinkMovie *)a; -+ -+ const QString title = ( lm->hasAnnotTitle() ? UnicodeParsedString( lm->getAnnotTitle() ) : QString() ); -+ -+ Ref reference; -+ reference.num = reference.gen = -1; -+ if ( lm->hasAnnotRef() ) -+ reference = *lm->getAnnotRef(); -+ -+ LinkMovie::Operation operation = LinkMovie::Play; -+ switch ( lm->getOperation() ) -+ { -+ case ::LinkMovie::operationTypePlay: -+ operation = LinkMovie::Play; -+ break; -+ case ::LinkMovie::operationTypePause: -+ operation = LinkMovie::Pause; -+ break; -+ case ::LinkMovie::operationTypeResume: -+ operation = LinkMovie::Resume; -+ break; -+ case ::LinkMovie::operationTypeStop: -+ operation = LinkMovie::Stop; -+ break; -+ }; -+ -+ popplerLink = new LinkMovie( linkArea, operation, title, reference ); -+ } -+ break; -+ -+ case actionRendition: -+ { -+ ::LinkRendition *lrn = (::LinkRendition *)a; -+ -+ Ref reference; -+ reference.num = reference.gen = -1; -+ if ( lrn->hasScreenAnnot() ) -+ reference = lrn->getScreenAnnot(); -+ -+ popplerLink = new LinkRendition( linkArea, lrn->getMedia() ? lrn->getMedia()->copy() : NULL, lrn->getOperation(), UnicodeParsedString( lrn->getScript() ), reference ); -+ } -+ break; -+ -+ case actionOCGState: -+ { -+ ::LinkOCGState *plocg = (::LinkOCGState *)a; -+ -+ LinkOCGStatePrivate *locgp = new LinkOCGStatePrivate( linkArea, plocg ); -+ popplerLink = new LinkOCGState( locgp ); -+ } -+ -+ case actionUnknown: -+ break; -+ } -+ -+ return popplerLink; -+} -+ -+inline TextPage *PageData::prepareTextSearch(const QString &text, Page::Rotation rotate, QVector *u) -+{ -+ const QChar * str = text.unicode(); -+ const int len = text.length(); -+ u->resize(len); -+ for (int i = 0; i < len; ++i) (*u)[i] = str[i].unicode(); -+ -+ const int rotation = (int)rotate * 90; -+ -+ // fetch ourselves a textpage -+ TextOutputDev td(NULL, true, 0, false, false); -+ parentDoc->doc->displayPage( &td, index + 1, 72, 72, rotation, false, true, false, -+ NULL, NULL, NULL, NULL, true); -+ TextPage *textPage=td.takeText(); -+ -+ return textPage; -+} -+ -+inline bool PageData::performSingleTextSearch(TextPage* textPage, QVector &u, double &sLeft, double &sTop, double &sRight, double &sBottom, Page::SearchDirection direction, bool sCase, bool sWords) -+{ -+ if (direction == Page::FromTop) -+ return textPage->findText( u.data(), u.size(), -+ true, true, false, false, sCase, false, sWords, &sLeft, &sTop, &sRight, &sBottom ); -+ else if ( direction == Page::NextResult ) -+ return textPage->findText( u.data(), u.size(), -+ false, true, true, false, sCase, false, sWords, &sLeft, &sTop, &sRight, &sBottom ); -+ else if ( direction == Page::PreviousResult ) -+ return textPage->findText( u.data(), u.size(), -+ false, true, true, false, sCase, true, sWords, &sLeft, &sTop, &sRight, &sBottom ); -+ -+ return false; -+} -+ -+inline QList PageData::performMultipleTextSearch(TextPage* textPage, QVector &u, bool sCase, bool sWords) -+{ -+ QList results; -+ double sLeft = 0.0, sTop = 0.0, sRight = 0.0, sBottom = 0.0; -+ -+ while(textPage->findText( u.data(), u.size(), -+ false, true, true, false, sCase, false, sWords, &sLeft, &sTop, &sRight, &sBottom )) -+ { -+ QRectF result; -+ -+ result.setLeft(sLeft); -+ result.setTop(sTop); -+ result.setRight(sRight); -+ result.setBottom(sBottom); -+ -+ results.append(result); -+ } -+ -+ return results; -+} -+ -+Page::Page(DocumentData *doc, int index) { -+ m_page = new PageData(); -+ m_page->index = index; -+ m_page->parentDoc = doc; -+ m_page->page = doc->doc->getPage(m_page->index + 1); -+ m_page->transition = 0; -+} -+ -+Page::~Page() -+{ -+ delete m_page->transition; -+ delete m_page; -+} -+ -+QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h, Rotation rotate) const -+{ -+ int rotation = (int)rotate * 90; -+ QImage img; -+ switch(m_page->parentDoc->m_backend) -+ { -+ case Poppler::Document::SplashBackend: -+ { -+#if defined(HAVE_SPLASH) -+ SplashColor bgColor; -+ bool overprintPreview = false; -+#ifdef SPLASH_CMYK -+ overprintPreview = m_page->parentDoc->m_hints & Document::OverprintPreview ? true : false; -+ if (overprintPreview) -+ { -+ Guchar c, m, y, k; -+ -+ c = 255 - m_page->parentDoc->paperColor.blue(); -+ m = 255 - m_page->parentDoc->paperColor.red(); -+ y = 255 - m_page->parentDoc->paperColor.green(); -+ k = c; -+ if (m < k) { -+ k = m; -+ } -+ if (y < k) { -+ k = y; -+ } -+ bgColor[0] = c - k; -+ bgColor[1] = m - k; -+ bgColor[2] = y - k; -+ bgColor[3] = k; -+ for (int i = 4; i < SPOT_NCOMPS + 4; i++) { -+ bgColor[i] = 0; -+ } -+ } -+ else -+#endif -+ { -+ bgColor[0] = m_page->parentDoc->paperColor.blue(); -+ bgColor[1] = m_page->parentDoc->paperColor.green(); -+ bgColor[2] = m_page->parentDoc->paperColor.red(); -+ } -+ -+ SplashColorMode colorMode = splashModeXBGR8; -+#ifdef SPLASH_CMYK -+ if (overprintPreview) colorMode = splashModeDeviceN8; -+#endif -+ -+ SplashThinLineMode thinLineMode = splashThinLineDefault; -+ if (m_page->parentDoc->m_hints & Document::ThinLineShape) thinLineMode = splashThinLineShape; -+ if (m_page->parentDoc->m_hints & Document::ThinLineSolid) thinLineMode = splashThinLineSolid; -+ -+ const bool ignorePaperColor = m_page->parentDoc->m_hints & Document::IgnorePaperColor; -+ -+ SplashOutputDev splash_output( -+ colorMode, 4, -+ false, -+ ignorePaperColor ? NULL : bgColor, -+ true, -+ thinLineMode, -+ overprintPreview); -+ -+ splash_output.setFontAntialias(m_page->parentDoc->m_hints & Document::TextAntialiasing ? true : false); -+ splash_output.setVectorAntialias(m_page->parentDoc->m_hints & Document::Antialiasing ? true : false); -+ splash_output.setFreeTypeHinting(m_page->parentDoc->m_hints & Document::TextHinting ? true : false, -+ m_page->parentDoc->m_hints & Document::TextSlightHinting ? true : false); -+ -+ splash_output.startDoc(m_page->parentDoc->doc); -+ -+ m_page->parentDoc->doc->displayPageSlice(&splash_output, m_page->index + 1, xres, yres, -+ rotation, false, true, false, x, y, w, h, -+ NULL, NULL, NULL, NULL, true); -+ -+ SplashBitmap *bitmap = splash_output.getBitmap(); -+ -+ const int bw = bitmap->getWidth(); -+ const int bh = bitmap->getHeight(); -+ const int brs = bitmap->getRowSize(); -+ -+ // If we use DeviceN8, convert to XBGR8. -+ // If requested, also transfer Splash's internal alpha channel. -+ const SplashBitmap::ConversionMode mode = ignorePaperColor -+ ? SplashBitmap::conversionAlphaPremultiplied -+ : SplashBitmap::conversionOpaque; -+ -+ const QImage::Format format = ignorePaperColor -+ ? QImage::Format_ARGB32_Premultiplied -+ : QImage::Format_RGB32; -+ -+ if (bitmap->convertToXBGR(mode)) { -+ SplashColorPtr data = bitmap->getDataPtr(); -+ -+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { -+ // Convert byte order from RGBX to XBGR. -+ for (int i = 0; i < bh; ++i) { -+ for (int j = 0; j < bw; ++j) { -+ SplashColorPtr pixel = &data[i * brs + j]; -+ -+ qSwap(pixel[0], pixel[3]); -+ qSwap(pixel[1], pixel[2]); -+ } -+ } -+ } -+ -+ // Construct a Qt image sharing the raw bitmap data. -+ img = QImage(data, bw, bh, brs, format).copy(); -+ } -+#endif -+ break; -+ } -+ case Poppler::Document::ArthurBackend: -+ { -+ QSize size = pageSize(); -+ QImage tmpimg(w == -1 ? qRound( size.width() * xres / 72.0 ) : w, h == -1 ? qRound( size.height() * yres / 72.0 ) : h, QImage::Format_ARGB32); -+ -+ QPainter painter(&tmpimg); -+ renderToPainter(&painter, xres, yres, x, y, w, h, rotate, DontSaveAndRestore); -+ painter.end(); -+ img = tmpimg; -+ break; -+ } -+ } -+ -+ return img; -+} -+ -+bool Page::renderToPainter(QPainter* painter, double xres, double yres, int x, int y, int w, int h, Rotation rotate, PainterFlags flags) const -+{ -+ if (!painter) -+ return false; -+ -+ switch(m_page->parentDoc->m_backend) -+ { -+ case Poppler::Document::SplashBackend: -+ return false; -+ case Poppler::Document::ArthurBackend: -+ { -+ const bool savePainter = !(flags & DontSaveAndRestore); -+ if (savePainter) -+ painter->save(); -+ if (m_page->parentDoc->m_hints & Document::Antialiasing) -+ painter->setRenderHint(QPainter::Antialiasing); -+ if (m_page->parentDoc->m_hints & Document::TextAntialiasing) -+ painter->setRenderHint(QPainter::TextAntialiasing); -+ painter->translate(x == -1 ? 0 : -x, y == -1 ? 0 : -y); -+ ArthurOutputDev arthur_output(painter); -+ arthur_output.startDoc(m_page->parentDoc->doc->getXRef()); -+ m_page->parentDoc->doc->displayPageSlice(&arthur_output, -+ m_page->index + 1, -+ xres, -+ yres, -+ (int)rotate * 90, -+ false, -+ true, -+ false, -+ x, -+ y, -+ w, -+ h); -+ if (savePainter) -+ painter->restore(); -+ return true; -+ } -+ } -+ return false; -+} -+ -+QImage Page::thumbnail() const -+{ -+ unsigned char* data = 0; -+ int w = 0; -+ int h = 0; -+ int rowstride = 0; -+ bool r = m_page->page->loadThumb(&data, &w, &h, &rowstride); -+ QImage ret; -+ if (r) -+ { -+ // first construct a temporary image with the data got, -+ // then force a copy of it so we can free the raw thumbnail data -+ ret = QImage(data, w, h, rowstride, QImage::Format_RGB888).copy(); -+ gfree(data); -+ } -+ return ret; -+} -+ -+QString Page::text(const QRectF &r, TextLayout textLayout) const -+{ -+ TextOutputDev *output_dev; -+ GooString *s; -+ const PDFRectangle *rect; -+ QString result; -+ -+ const bool rawOrder = textLayout == RawOrderLayout; -+ output_dev = new TextOutputDev(0, false, 0, rawOrder, false); -+ m_page->parentDoc->doc->displayPageSlice(output_dev, m_page->index + 1, 72, 72, -+ 0, false, true, false, -1, -1, -1, -1, -+ NULL, NULL, NULL, NULL, true); -+ if (r.isNull()) -+ { -+ rect = m_page->page->getCropBox(); -+ s = output_dev->getText(rect->x1, rect->y1, rect->x2, rect->y2); -+ } -+ else -+ { -+ s = output_dev->getText(r.left(), r.top(), r.right(), r.bottom()); -+ } -+ -+ result = QString::fromUtf8(s->c_str()); -+ -+ delete output_dev; -+ delete s; -+ return result; -+} -+ -+QString Page::text(const QRectF &r) const -+{ -+ return text(r, PhysicalLayout); -+} -+ -+bool Page::search(const QString &text, double &sLeft, double &sTop, double &sRight, double &sBottom, SearchDirection direction, SearchMode caseSensitive, Rotation rotate) const -+{ -+ const bool sCase = caseSensitive == Page::CaseSensitive ? true : false; -+ -+ QVector u; -+ TextPage *textPage = m_page->prepareTextSearch(text, rotate, &u); -+ -+ const bool found = m_page->performSingleTextSearch(textPage, u, sLeft, sTop, sRight, sBottom, direction, sCase, false); -+ -+ textPage->decRefCnt(); -+ -+ return found; -+} -+ -+bool Page::search(const QString &text, double &sLeft, double &sTop, double &sRight, double &sBottom, SearchDirection direction, SearchFlags flags, Rotation rotate) const -+{ -+ const bool sCase = flags.testFlag(IgnoreCase) ? false : true; -+ const bool sWords = flags.testFlag(WholeWords) ? true : false; -+ -+ QVector u; -+ TextPage *textPage = m_page->prepareTextSearch(text, rotate, &u); -+ -+ const bool found = m_page->performSingleTextSearch(textPage, u, sLeft, sTop, sRight, sBottom, direction, sCase, sWords); -+ -+ textPage->decRefCnt(); -+ -+ return found; -+} -+ -+bool Page::search(const QString &text, QRectF &rect, SearchDirection direction, SearchMode caseSensitive, Rotation rotate) const -+{ -+ double sLeft, sTop, sRight, sBottom; -+ sLeft = rect.left(); -+ sTop = rect.top(); -+ sRight = rect.right(); -+ sBottom = rect.bottom(); -+ -+ bool found = search(text, sLeft, sTop, sRight, sBottom, direction, caseSensitive, rotate); -+ -+ rect.setLeft( sLeft ); -+ rect.setTop( sTop ); -+ rect.setRight( sRight ); -+ rect.setBottom( sBottom ); -+ -+ return found; -+} -+ -+QList Page::search(const QString &text, SearchMode caseSensitive, Rotation rotate) const -+{ -+ const bool sCase = caseSensitive == Page::CaseSensitive ? true : false; -+ -+ QVector u; -+ TextPage *textPage = m_page->prepareTextSearch(text, rotate, &u); -+ -+ const QList results = m_page->performMultipleTextSearch(textPage, u, sCase, false); -+ -+ textPage->decRefCnt(); -+ -+ return results; -+} -+ -+QList Page::search(const QString &text, SearchFlags flags, Rotation rotate) const -+{ -+ const bool sCase = flags.testFlag(IgnoreCase) ? false : true; -+ const bool sWords = flags.testFlag(WholeWords) ? true : false; -+ -+ QVector u; -+ TextPage *textPage = m_page->prepareTextSearch(text, rotate, &u); -+ -+ const QList results = m_page->performMultipleTextSearch(textPage, u, sCase, sWords); -+ -+ textPage->decRefCnt(); -+ -+ return results; -+} -+ -+QList Page::textList(Rotation rotate) const -+{ -+ TextOutputDev *output_dev; -+ -+ QList output_list; -+ -+ output_dev = new TextOutputDev(0, false, 0, false, false); -+ -+ int rotation = (int)rotate * 90; -+ -+ m_page->parentDoc->doc->displayPageSlice(output_dev, m_page->index + 1, 72, 72, -+ rotation, false, false, false, -1, -1, -1, -1, -+ NULL, NULL, NULL, NULL, true); -+ -+ TextWordList *word_list = output_dev->makeWordList(); -+ -+ if (!word_list) { -+ delete output_dev; -+ return output_list; -+ } -+ -+ QHash wordBoxMap; -+ -+ output_list.reserve(word_list->getLength()); -+ for (int i = 0; i < word_list->getLength(); i++) { -+ TextWord *word = word_list->get(i); -+ GooString *gooWord = word->getText(); -+ QString string = QString::fromUtf8(gooWord->c_str()); -+ delete gooWord; -+ double xMin, yMin, xMax, yMax; -+ word->getBBox(&xMin, &yMin, &xMax, &yMax); -+ -+ TextBox* text_box = new TextBox(string, QRectF(xMin, yMin, xMax-xMin, yMax-yMin)); -+ text_box->m_data->hasSpaceAfter = word->hasSpaceAfter() == true; -+ text_box->m_data->charBBoxes.reserve(word->getLength()); -+ for (int j = 0; j < word->getLength(); ++j) -+ { -+ word->getCharBBox(j, &xMin, &yMin, &xMax, &yMax); -+ text_box->m_data->charBBoxes.append(QRectF(xMin, yMin, xMax-xMin, yMax-yMin)); -+ } -+ -+ wordBoxMap.insert(word, text_box); -+ -+ output_list.append(text_box); -+ } -+ -+ for (int i = 0; i < word_list->getLength(); i++) { -+ TextWord *word = word_list->get(i); -+ TextBox* text_box = wordBoxMap.value(word); -+ text_box->m_data->nextWord = wordBoxMap.value(word->nextWord()); -+ } -+ -+ delete word_list; -+ delete output_dev; -+ -+ return output_list; -+} -+ -+PageTransition *Page::transition() const -+{ -+ if (!m_page->transition) { -+ PageTransitionParams params; -+ Object o = m_page->page->getTrans(); -+ params.dictObj = &o; -+ if (o.isDict()) m_page->transition = new PageTransition(params); -+ } -+ return m_page->transition; -+} -+ -+Link *Page::action( PageAction act ) const -+{ -+ if ( act == Page::Opening || act == Page::Closing ) -+ { -+ Object o = m_page->page->getActions(); -+ if (!o.isDict()) -+ { -+ return 0; -+ } -+ Dict *dict = o.getDict(); -+ const char *key = act == Page::Opening ? "O" : "C"; -+ Object o2 = dict->lookup((char*)key); -+ ::LinkAction *lact = ::LinkAction::parseAction(&o2, m_page->parentDoc->doc->getCatalog()->getBaseURI() ); -+ Link *popplerLink = NULL; -+ if (lact != NULL) -+ { -+ popplerLink = m_page->convertLinkActionToLink(lact, QRectF()); -+ delete lact; -+ } -+ return popplerLink; -+ } -+ return 0; -+} -+ -+QSizeF Page::pageSizeF() const -+{ -+ Page::Orientation orient = orientation(); -+ if ( ( Page::Landscape == orient ) || (Page::Seascape == orient ) ) { -+ return QSizeF( m_page->page->getCropHeight(), m_page->page->getCropWidth() ); -+ } else { -+ return QSizeF( m_page->page->getCropWidth(), m_page->page->getCropHeight() ); -+ } -+} -+ -+QSize Page::pageSize() const -+{ -+ return pageSizeF().toSize(); -+} -+ -+Page::Orientation Page::orientation() const -+{ -+ const int rotation = m_page->page->getRotate(); -+ switch (rotation) { -+ case 90: -+ return Page::Landscape; -+ break; -+ case 180: -+ return Page::UpsideDown; -+ break; -+ case 270: -+ return Page::Seascape; -+ break; -+ default: -+ return Page::Portrait; -+ } -+} -+ -+void Page::defaultCTM(double *CTM, double dpiX, double dpiY, int rotate, bool upsideDown) -+{ -+ m_page->page->getDefaultCTM(CTM, dpiX, dpiY, rotate, false, upsideDown); -+} -+ -+QList Page::links() const -+{ -+ LinkExtractorOutputDev link_dev(m_page); -+ m_page->parentDoc->doc->processLinks(&link_dev, m_page->index + 1); -+ QList popplerLinks = link_dev.links(); -+ -+ return popplerLinks; -+} -+ -+QList Page::annotations() const -+{ -+ return AnnotationPrivate::findAnnotations(m_page->page, m_page->parentDoc, QSet()); -+} -+ -+QList Page::annotations(const QSet &subtypes) const -+{ -+ return AnnotationPrivate::findAnnotations(m_page->page, m_page->parentDoc, subtypes); -+} -+ -+void Page::addAnnotation( const Annotation *ann ) -+{ -+ AnnotationPrivate::addAnnotationToPage(m_page->page, m_page->parentDoc, ann); -+} -+ -+void Page::removeAnnotation( const Annotation *ann ) -+{ -+ AnnotationPrivate::removeAnnotationFromPage(m_page->page, ann); -+} -+ -+QList Page::formFields() const -+{ -+ QList fields; -+ ::Page *p = m_page->page; -+ ::FormPageWidgets * form = p->getFormWidgets(); -+ int formcount = form->getNumWidgets(); -+ for (int i = 0; i < formcount; ++i) -+ { -+ ::FormWidget *fm = form->getWidget(i); -+ FormField * ff = NULL; -+ switch (fm->getType()) -+ { -+ case formButton: -+ { -+ ff = new FormFieldButton(m_page->parentDoc, p, static_cast(fm)); -+ } -+ break; -+ -+ case formText: -+ { -+ ff = new FormFieldText(m_page->parentDoc, p, static_cast(fm)); -+ } -+ break; -+ -+ case formChoice: -+ { -+ ff = new FormFieldChoice(m_page->parentDoc, p, static_cast(fm)); -+ } -+ break; -+ -+ default: ; -+ } -+ -+ if (ff) -+ fields.append(ff); -+ } -+ -+ delete form; -+ -+ return fields; -+} -+ -+double Page::duration() const -+{ -+ return m_page->page->getDuration(); -+} -+ -+QString Page::label() const -+{ -+ GooString goo; -+ if (!m_page->parentDoc->doc->getCatalog()->indexToLabel(m_page->index, &goo)) -+ return QString(); -+ -+ return UnicodeParsedString(&goo); -+} -+ -+ -+} -diff --git a/qt4/src/poppler-pdf-converter.cc b/qt4/src/poppler-pdf-converter.cc -new file mode 100644 -index 00000000..9699b75b ---- /dev/null -+++ b/qt4/src/poppler-pdf-converter.cc -@@ -0,0 +1,115 @@ -+/* poppler-pdf-converter.cc: qt4 interface to poppler -+ * Copyright (C) 2008, Pino Toscano -+ * Copyright (C) 2008, 2009, Albert Astals Cid -+ * -+ * 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-qt4.h" -+ -+#include "poppler-private.h" -+#include "poppler-converter-private.h" -+#include "poppler-qiodeviceoutstream-private.h" -+ -+#include -+ -+#include -+ -+namespace Poppler { -+ -+class PDFConverterPrivate : public BaseConverterPrivate -+{ -+ public: -+ PDFConverterPrivate(); -+ -+ PDFConverter::PDFOptions opts; -+}; -+ -+PDFConverterPrivate::PDFConverterPrivate() -+ : BaseConverterPrivate(), opts(0) -+{ -+} -+ -+ -+PDFConverter::PDFConverter(DocumentData *document) -+ : BaseConverter(*new PDFConverterPrivate()) -+{ -+ Q_D(PDFConverter); -+ d->document = document; -+} -+ -+PDFConverter::~PDFConverter() -+{ -+} -+ -+void PDFConverter::setPDFOptions(PDFConverter::PDFOptions options) -+{ -+ Q_D(PDFConverter); -+ d->opts = options; -+} -+ -+PDFConverter::PDFOptions PDFConverter::pdfOptions() const -+{ -+ Q_D(const PDFConverter); -+ return d->opts; -+} -+ -+bool PDFConverter::convert() -+{ -+ Q_D(PDFConverter); -+ d->lastError = NoError; -+ -+ if (d->document->locked) -+ { -+ d->lastError = FileLockedError; -+ return false; -+ } -+ -+ QIODevice *dev = d->openDevice(); -+ if (!dev) -+ { -+ d->lastError = OpenOutputError; -+ return false; -+ } -+ -+ bool deleteFile = false; -+ if (QFile *file = qobject_cast(dev)) -+ deleteFile = !file->exists(); -+ -+ int errorCode = errNone; -+ QIODeviceOutStream stream(dev); -+ if (d->opts & WithChanges) -+ { -+ errorCode = d->document->doc->saveAs(&stream); -+ } -+ else -+ { -+ errorCode = d->document->doc->saveWithoutChangesAs(&stream); -+ } -+ d->closeDevice(); -+ if (errorCode != errNone) -+ { -+ if (deleteFile) -+ { -+ qobject_cast(dev)->remove(); -+ } -+ if (errorCode == errOpenFile) d->lastError = OpenOutputError; -+ else d->lastError = NotSupportedInputFileError; -+ } -+ -+ return (errorCode == errNone); -+} -+ -+} -diff --git a/qt4/src/poppler-private.cc b/qt4/src/poppler-private.cc -new file mode 100644 -index 00000000..1338a185 ---- /dev/null -+++ b/qt4/src/poppler-private.cc -@@ -0,0 +1,296 @@ -+/* poppler-private.cc: qt interface to poppler -+ * Copyright (C) 2005, Net Integration Technologies, Inc. -+ * Copyright (C) 2006, 2011, 2015, 2017 by Albert Astals Cid -+ * Copyright (C) 2008, 2010, 2011 by Pino Toscano -+ * Copyright (C) 2013 by Thomas Freitag -+ * Copyright (C) 2013 Adrian Johnson -+ * Copyright (C) 2016 Jakub Alba -+ * Inspired on code by -+ * Copyright (C) 2004 by Albert Astals Cid -+ * Copyright (C) 2004 by Enrico Ros -+ * -+ * 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-private.h" -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+namespace Poppler { -+ -+namespace Debug { -+ -+ static void qDebugDebugFunction(const QString &message, const QVariant & /*closure*/) -+ { -+ qDebug() << message; -+ } -+ -+ PopplerDebugFunc debugFunction = qDebugDebugFunction; -+ QVariant debugClosure; -+ -+} -+ -+ static UnicodeMap *utf8Map = 0; -+ -+ void setDebugErrorFunction(PopplerDebugFunc function, const QVariant &closure) -+ { -+ Debug::debugFunction = function ? function : Debug::qDebugDebugFunction; -+ Debug::debugClosure = closure; -+ } -+ -+ static void qt4ErrorFunction(void * /*data*/, ErrorCategory /*category*/, Goffset pos, const char *msg) -+ { -+ QString emsg; -+ -+ if (pos >= 0) -+ { -+ emsg = QString::fromLatin1("Error (%1): ").arg(pos); -+ } -+ else -+ { -+ emsg = QString::fromLatin1("Error: "); -+ } -+ emsg += QString::fromAscii(msg); -+ (*Debug::debugFunction)(emsg, Debug::debugClosure); -+ } -+ -+ QString unicodeToQString(const Unicode* u, int len) { -+ if (!utf8Map) -+ { -+ GooString enc("UTF-8"); -+ utf8Map = globalParams->getUnicodeMap(&enc); -+ utf8Map->incRefCnt(); -+ } -+ -+ // ignore the last character if it is 0x0 -+ if ((len > 0) && (u[len - 1] == 0)) -+ { -+ --len; -+ } -+ -+ GooString convertedStr; -+ for (int i = 0; i < len; ++i) -+ { -+ char buf[8]; -+ const int n = utf8Map->mapUnicode(u[i], buf, sizeof(buf)); -+ convertedStr.append(buf, n); -+ } -+ -+ return QString::fromUtf8(convertedStr.c_str(), convertedStr.getLength()); -+ } -+ -+ QString UnicodeParsedString(const GooString *s1) { -+ if ( !s1 || s1->getLength() == 0 ) -+ return QString(); -+ -+ const char *cString; -+ int stringLength; -+ bool deleteCString; -+ if ( ( s1->getChar(0) & 0xff ) == 0xfe && ( s1->getLength() > 1 && ( s1->getChar(1) & 0xff ) == 0xff ) ) -+ { -+ cString = s1->c_str(); -+ stringLength = s1->getLength(); -+ deleteCString = false; -+ } -+ else -+ { -+ cString = pdfDocEncodingToUTF16(s1, &stringLength); -+ deleteCString = true; -+ } -+ -+ QString result; -+ // i = 2 to skip the unicode marker -+ for ( int i = 2; i < stringLength; i += 2 ) -+ { -+ const Unicode u = ( ( cString[i] & 0xff ) << 8 ) | ( cString[i+1] & 0xff ); -+ result += QChar( u ); -+ } -+ if (deleteCString) -+ delete[] cString; -+ return result; -+ } -+ -+ GooString *QStringToUnicodeGooString(const QString &s) { -+ int len = s.length() * 2 + 2; -+ char *cstring = (char *)gmallocn(len, sizeof(char)); -+ cstring[0] = (char)0xfe; -+ cstring[1] = (char)0xff; -+ for (int i = 0; i < s.length(); ++i) -+ { -+ cstring[2+i*2] = s.at(i).row(); -+ cstring[3+i*2] = s.at(i).cell(); -+ } -+ GooString *ret = new GooString(cstring, len); -+ gfree(cstring); -+ return ret; -+ } -+ -+ GooString *QStringToGooString(const QString &s) { -+ int len = s.length(); -+ char *cstring = (char *)gmallocn(s.length(), sizeof(char)); -+ for (int i = 0; i < len; ++i) -+ cstring[i] = s.at(i).unicode(); -+ GooString *ret = new GooString(cstring, len); -+ gfree(cstring); -+ return ret; -+ } -+ -+ GooString *QDateTimeToUnicodeGooString(const QDateTime &dt) { -+ if (!dt.isValid()) { -+ return NULL; -+ } -+ -+ return QStringToUnicodeGooString(dt.toUTC().toString("yyyyMMddhhmmss+00'00'")); -+ } -+ -+ static void linkActionToTocItem( const ::LinkAction * a, DocumentData * doc, QDomElement * e ) -+ { -+ if ( !a || !e ) -+ return; -+ -+ switch ( a->getKind() ) -+ { -+ case actionGoTo: -+ { -+ // page number is contained/referenced in a LinkGoTo -+ const LinkGoTo * g = static_cast< const LinkGoTo * >( a ); -+ const LinkDest * destination = g->getDest(); -+ if ( !destination && g->getNamedDest() ) -+ { -+ // no 'destination' but an internal 'named reference'. we could -+ // get the destination for the page now, but it's VERY time consuming, -+ // so better storing the reference and provide the viewport on demand -+ const GooString *s = g->getNamedDest(); -+ QChar *charArray = new QChar[s->getLength()]; -+ for (int i = 0; i < s->getLength(); ++i) charArray[i] = QChar(s->c_str()[i]); -+ QString aux(charArray, s->getLength()); -+ e->setAttribute( "DestinationName", aux ); -+ delete[] charArray; -+ } -+ else if ( destination && destination->isOk() ) -+ { -+ LinkDestinationData ldd(destination, NULL, doc, false); -+ e->setAttribute( "Destination", LinkDestination(ldd).toString() ); -+ } -+ break; -+ } -+ case actionGoToR: -+ { -+ // page number is contained/referenced in a LinkGoToR -+ const LinkGoToR * g = static_cast< const LinkGoToR * >( a ); -+ const LinkDest * destination = g->getDest(); -+ if ( !destination && g->getNamedDest() ) -+ { -+ // no 'destination' but an internal 'named reference'. we could -+ // get the destination for the page now, but it's VERY time consuming, -+ // so better storing the reference and provide the viewport on demand -+ const GooString *s = g->getNamedDest(); -+ QChar *charArray = new QChar[s->getLength()]; -+ for (int i = 0; i < s->getLength(); ++i) charArray[i] = QChar(s->c_str()[i]); -+ QString aux(charArray, s->getLength()); -+ e->setAttribute( "DestinationName", aux ); -+ delete[] charArray; -+ } -+ else if ( destination && destination->isOk() ) -+ { -+ LinkDestinationData ldd(destination, NULL, doc, g->getFileName() != 0); -+ e->setAttribute( "Destination", LinkDestination(ldd).toString() ); -+ } -+ e->setAttribute( "ExternalFileName", g->getFileName()->c_str() ); -+ break; -+ } -+ case actionURI: -+ { -+ const LinkURI * u = static_cast< const LinkURI * >( a ); -+ e->setAttribute( "DestinationURI", u->getURI()->c_str() ); -+ } -+ default: ; -+ } -+ } -+ -+ DocumentData::~DocumentData() -+ { -+ qDeleteAll(m_embeddedFiles); -+ delete (OptContentModel *)m_optContentModel; -+ delete doc; -+ delete m_fontInfoIterator; -+ -+ count --; -+ if ( count == 0 ) -+ { -+ utf8Map = nullptr; -+ globalParams.reset(); -+ } -+ } -+ -+ void DocumentData::init() -+ { -+ m_fontInfoIterator = 0; -+ m_backend = Document::SplashBackend; -+ paperColor = Qt::white; -+ m_hints = 0; -+ m_optContentModel = 0; -+ -+ if ( count == 0 ) -+ { -+ utf8Map = nullptr; -+ globalParams = std::make_unique(); -+ setErrorCallback(qt4ErrorFunction, nullptr); -+ } -+ count ++; -+ } -+ -+ -+ void DocumentData::addTocChildren( QDomDocument * docSyn, QDomNode * parent, const std::vector<::OutlineItem*> * items ) -+ { -+ -+ for ( ::OutlineItem * outlineItem : *items ) -+ { -+ // iterate over every object in 'items' -+ -+ -+ // 1. create element using outlineItem's title as tagName -+ QString name; -+ const Unicode * uniChar = outlineItem->getTitle(); -+ int titleLength = outlineItem->getTitleLength(); -+ name = unicodeToQString(uniChar, titleLength); -+ if ( name.isEmpty() ) -+ continue; -+ -+ QDomElement item = docSyn->createElement( name ); -+ parent->appendChild( item ); -+ -+ // 2. find the page the link refers to -+ const ::LinkAction * a = outlineItem->getAction(); -+ linkActionToTocItem( a, this, &item ); -+ -+ item.setAttribute( "Open", QVariant( (bool)outlineItem->isOpen() ).toString() ); -+ -+ // 3. recursively descend over children -+ outlineItem->open(); -+ const std::vector<::OutlineItem*> * children = outlineItem->getKids(); -+ if ( children ) -+ addTocChildren( docSyn, &item, children ); -+ } -+ } -+ -+} -diff --git a/qt4/src/poppler-private.h b/qt4/src/poppler-private.h -new file mode 100644 -index 00000000..a5ad3f3e ---- /dev/null -+++ b/qt4/src/poppler-private.h -@@ -0,0 +1,242 @@ -+/* poppler-private.h: qt interface to poppler -+ * Copyright (C) 2005, Net Integration Technologies, Inc. -+ * Copyright (C) 2005, 2008, Brad Hards -+ * Copyright (C) 2006-2009, 2011, 2012, 2017 by Albert Astals Cid -+ * Copyright (C) 2007-2009, 2011 by Pino Toscano -+ * Copyright (C) 2011 Andreas Hartmetz -+ * Copyright (C) 2011 Hib Eris -+ * Copyright (C) 2012, 2013 Thomas Freitag -+ * Copyright (C) 2013 Julien Nabet -+ * Copyright (C) 2016 Jakub Alba -+ * Inspired on code by -+ * Copyright (C) 2004 by Albert Astals Cid -+ * Copyright (C) 2004 by Enrico Ros -+ * -+ * 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_PRIVATE_H_ -+#define _POPPLER_PRIVATE_H_ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if defined(HAVE_SPLASH) -+#include -+#endif -+ -+#include "poppler-qt4.h" -+#include "poppler-embeddedfile-private.h" -+ -+class LinkDest; -+class FormWidget; -+ -+namespace Poppler { -+ -+ /* borrowed from kpdf */ -+ QString unicodeToQString(Unicode* u, int len); -+ -+ QString UnicodeParsedString(GooString *s1); -+ -+ GooString *QStringToUnicodeGooString(const QString &s); -+ -+ GooString *QStringToGooString(const QString &s); -+ -+ GooString *QDateTimeToUnicodeGooString(const QDateTime &dt); -+ -+ void qt4ErrorFunction(int pos, char *msg, va_list args); -+ -+ class LinkDestinationData -+ { -+ public: -+ LinkDestinationData( LinkDest *l, GooString *nd, Poppler::DocumentData *pdfdoc, bool external ) -+ : ld(l), namedDest(nd), doc(pdfdoc), externalDest(external) -+ { -+ } -+ -+ LinkDest *ld; -+ GooString *namedDest; -+ Poppler::DocumentData *doc; -+ bool externalDest; -+ }; -+ -+ class DocumentData { -+ public: -+ DocumentData(const QString &filePath, GooString *ownerPassword, GooString *userPassword) -+ { -+ init(); -+ m_filePath = filePath; -+ -+#if defined(_WIN32) -+ wchar_t *fileName = new WCHAR[filePath.length()]; -+ int length = filePath.toWCharArray(fileName); -+ doc = new PDFDoc(fileName, length, ownerPassword, userPassword); -+ delete[] fileName; -+#else -+ GooString *fileName = new GooString(QFile::encodeName(filePath)); -+ doc = new PDFDoc(fileName, ownerPassword, userPassword); -+#endif -+ -+ delete ownerPassword; -+ delete userPassword; -+ } -+ -+ DocumentData(const QByteArray &data, GooString *ownerPassword, GooString *userPassword) -+ { -+ fileContents = data; -+ MemStream *str = new MemStream((char*)fileContents.data(), 0, fileContents.length(), Object(objNull)); -+ init(); -+ doc = new PDFDoc(str, ownerPassword, userPassword); -+ delete ownerPassword; -+ delete userPassword; -+ } -+ -+ void init(); -+ -+ ~DocumentData(); -+ -+ void addTocChildren( QDomDocument * docSyn, QDomNode * parent, const std::vector * items ); -+ -+ void setPaperColor(const QColor &color) -+ { -+ paperColor = color; -+ } -+ -+ void fillMembers() -+ { -+ m_fontInfoIterator = new FontIterator(0, this); -+ int numEmb = doc->getCatalog()->numEmbeddedFiles(); -+ if (!(0 == numEmb)) { -+ // we have some embedded documents, build the list -+ for (int yalv = 0; yalv < numEmb; ++yalv) { -+ FileSpec *fs = doc->getCatalog()->embeddedFile(yalv); -+ m_embeddedFiles.append(new EmbeddedFile(*new EmbeddedFileData(fs))); -+ } -+ } -+ } -+ -+ static Document *checkDocument(DocumentData *doc); -+ -+ PDFDoc *doc; -+ QString m_filePath; -+ QByteArray fileContents; -+ bool locked; -+ FontIterator *m_fontInfoIterator; -+ Document::RenderBackend m_backend; -+ QList m_embeddedFiles; -+ QPointer m_optContentModel; -+ QColor paperColor; -+ int m_hints; -+ static int count; -+ }; -+ -+ class FontInfoData -+ { -+ public: -+ FontInfoData() -+ { -+ isEmbedded = false; -+ isSubset = false; -+ type = FontInfo::unknown; -+ } -+ -+ FontInfoData( const FontInfoData &fid ) -+ { -+ fontName = fid.fontName; -+ fontFile = fid.fontFile; -+ isEmbedded = fid.isEmbedded; -+ isSubset = fid.isSubset; -+ type = fid.type; -+ embRef = fid.embRef; -+ } -+ -+ FontInfoData( ::FontInfo* fi ) -+ { -+ if (fi->getName()) fontName = fi->getName()->c_str(); -+ if (fi->getFile()) fontFile = fi->getFile()->c_str(); -+ isEmbedded = fi->getEmbedded(); -+ isSubset = fi->getSubset(); -+ type = (Poppler::FontInfo::Type)fi->getType(); -+ embRef = fi->getEmbRef(); -+ } -+ -+ QString fontName; -+ QString fontFile; -+ bool isEmbedded : 1; -+ bool isSubset : 1; -+ FontInfo::Type type; -+ Ref embRef; -+ }; -+ -+ class FontIteratorData -+ { -+ public: -+ FontIteratorData( int startPage, DocumentData *dd ) -+ : fontInfoScanner( dd->doc, startPage ) -+ , totalPages( dd->doc->getNumPages() ) -+ , currentPage( qMax( startPage, 0 ) - 1 ) -+ { -+ } -+ -+ ~FontIteratorData() -+ { -+ } -+ -+ FontInfoScanner fontInfoScanner; -+ int totalPages; -+ int currentPage; -+ }; -+ -+ class TextBoxData -+ { -+ public: -+ TextBoxData() -+ : nextWord(0), hasSpaceAfter(false) -+ { -+ } -+ -+ QString text; -+ QRectF bBox; -+ TextBox *nextWord; -+ QVector charBBoxes; // the boundingRect of each character -+ bool hasSpaceAfter; -+ }; -+ -+ class FormFieldData -+ { -+ public: -+ FormFieldData(DocumentData *_doc, ::Page *p, ::FormWidget *w) : -+ doc(_doc), page(p), fm(w) -+ { -+ } -+ -+ DocumentData *doc; -+ ::Page *page; -+ ::FormWidget *fm; -+ QRectF box; -+ }; -+ -+} -+ -+#endif -diff --git a/qt4/src/poppler-ps-converter.cc b/qt4/src/poppler-ps-converter.cc -new file mode 100644 -index 00000000..4b43d8ec ---- /dev/null -+++ b/qt4/src/poppler-ps-converter.cc -@@ -0,0 +1,280 @@ -+/* poppler-ps-converter.cc: qt interface to poppler -+ * Copyright (C) 2007, 2009, 2010, 2015, Albert Astals Cid -+ * Copyright (C) 2008, Pino Toscano -+ * Copyright (C) 2010 Hib Eris -+ * Copyright (C) 2011 Glad Deschrijver -+ * Copyright (C) 2012 Fabio D'Urso -+ * Copyright (C) 2013 Thomas Freitag -+ * Copyright (C) 2014 Adrian Johnson -+ * -+ * 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-qt4.h" -+ -+#include "poppler-private.h" -+#include "poppler-converter-private.h" -+ -+#include "PSOutputDev.h" -+ -+static void outputToQIODevice(void *stream, const char *data, int len) -+{ -+ static_cast(stream)->write(data, len); -+} -+ -+namespace Poppler { -+ -+class PSConverterPrivate : public BaseConverterPrivate -+{ -+ public: -+ PSConverterPrivate(); -+ -+ QList pageList; -+ QString title; -+ double hDPI; -+ double vDPI; -+ int rotate; -+ int paperWidth; -+ int paperHeight; -+ int marginRight; -+ int marginBottom; -+ int marginLeft; -+ int marginTop; -+ PSConverter::PSOptions opts; -+ void (* pageConvertedCallback)(int page, void *payload); -+ void *pageConvertedPayload; -+}; -+ -+PSConverterPrivate::PSConverterPrivate() -+ : BaseConverterPrivate(), -+ hDPI(72), vDPI(72), rotate(0), paperWidth(-1), paperHeight(-1), -+ marginRight(0), marginBottom(0), marginLeft(0), marginTop(0), -+ opts(PSConverter::Printing), pageConvertedCallback(0), -+ pageConvertedPayload(0) -+{ -+} -+ -+ -+PSConverter::PSConverter(DocumentData *document) -+ : BaseConverter(*new PSConverterPrivate()) -+{ -+ Q_D(PSConverter); -+ d->document = document; -+} -+ -+PSConverter::~PSConverter() -+{ -+} -+ -+void PSConverter::setPageList(const QList &pageList) -+{ -+ Q_D(PSConverter); -+ d->pageList = pageList; -+} -+ -+void PSConverter::setTitle(const QString &title) -+{ -+ Q_D(PSConverter); -+ d->title = title; -+} -+ -+void PSConverter::setHDPI(double hDPI) -+{ -+ Q_D(PSConverter); -+ d->hDPI = hDPI; -+} -+ -+void PSConverter::setVDPI(double vDPI) -+{ -+ Q_D(PSConverter); -+ d->vDPI = vDPI; -+} -+ -+void PSConverter::setRotate(int rotate) -+{ -+ Q_D(PSConverter); -+ d->rotate = rotate; -+} -+ -+void PSConverter::setPaperWidth(int paperWidth) -+{ -+ Q_D(PSConverter); -+ d->paperWidth = paperWidth; -+} -+ -+void PSConverter::setPaperHeight(int paperHeight) -+{ -+ Q_D(PSConverter); -+ d->paperHeight = paperHeight; -+} -+ -+void PSConverter::setRightMargin(int marginRight) -+{ -+ Q_D(PSConverter); -+ d->marginRight = marginRight; -+} -+ -+void PSConverter::setBottomMargin(int marginBottom) -+{ -+ Q_D(PSConverter); -+ d->marginBottom = marginBottom; -+} -+ -+void PSConverter::setLeftMargin(int marginLeft) -+{ -+ Q_D(PSConverter); -+ d->marginLeft = marginLeft; -+} -+ -+void PSConverter::setTopMargin(int marginTop) -+{ -+ Q_D(PSConverter); -+ d->marginTop = marginTop; -+} -+ -+void PSConverter::setStrictMargins(bool strictMargins) -+{ -+ Q_D(PSConverter); -+ if (strictMargins) -+ d->opts |= StrictMargins; -+ else -+ d->opts &= ~StrictMargins; -+} -+ -+void PSConverter::setForceRasterize(bool forceRasterize) -+{ -+ Q_D(PSConverter); -+ if (forceRasterize) -+ d->opts |= ForceRasterization; -+ else -+ d->opts &= ~ForceRasterization; -+} -+ -+void PSConverter::setPSOptions(PSConverter::PSOptions options) -+{ -+ Q_D(PSConverter); -+ d->opts = options; -+} -+ -+PSConverter::PSOptions PSConverter::psOptions() const -+{ -+ Q_D(const PSConverter); -+ return d->opts; -+} -+ -+void PSConverter::setPageConvertedCallback(void (* callback)(int page, void *payload), void *payload) -+{ -+ Q_D(PSConverter); -+ d->pageConvertedCallback = callback; -+ d->pageConvertedPayload = payload; -+} -+ -+static bool annotDisplayDecideCbk(Annot *annot, void *user_data) -+{ -+ if (annot->getType() == Annot::typeWidget) -+ return true; // Never hide forms -+ else -+ return *(bool*)user_data; -+} -+ -+bool PSConverter::convert() -+{ -+ Q_D(PSConverter); -+ d->lastError = NoError; -+ -+ Q_ASSERT(!d->pageList.isEmpty()); -+ Q_ASSERT(d->paperWidth != -1); -+ Q_ASSERT(d->paperHeight != -1); -+ -+ if (d->document->locked) -+ { -+ d->lastError = FileLockedError; -+ return false; -+ } -+ -+ QIODevice *dev = d->openDevice(); -+ if (!dev) -+ { -+ d->lastError = OpenOutputError; -+ return false; -+ } -+ -+ QByteArray pstitle8Bit = d->title.toLocal8Bit(); -+ char* pstitlechar; -+ if (!d->title.isEmpty()) pstitlechar = pstitle8Bit.data(); -+ else pstitlechar = 0; -+ -+ std::vector pages; -+ foreach(int page, d->pageList) -+ { -+ pages.push_back(page); -+ } -+ -+ PSOutputDev *psOut = new PSOutputDev(outputToQIODevice, dev, -+ pstitlechar, -+ d->document->doc, -+ pages, -+ (d->opts & PrintToEPS) ? psModeEPS : psModePS, -+ d->paperWidth, -+ d->paperHeight, -+ false, -+ false, -+ d->marginLeft, -+ d->marginBottom, -+ d->paperWidth - d->marginRight, -+ d->paperHeight - d->marginTop, -+ (d->opts & ForceRasterization)); -+ -+ if (d->opts & StrictMargins) -+ { -+ double xScale = ((double)d->paperWidth - (double)d->marginLeft - (double)d->marginRight) / (double)d->paperWidth; -+ double yScale = ((double)d->paperHeight - (double)d->marginBottom - (double)d->marginTop) / (double)d->paperHeight; -+ psOut->setScale(xScale, yScale); -+ } -+ -+ if (psOut->isOk()) -+ { -+ bool isPrinting = (d->opts & Printing) ? true : false; -+ bool showAnnotations = (d->opts & HideAnnotations) ? false : true; -+ foreach(int page, d->pageList) -+ { -+ d->document->doc->displayPage(psOut, -+ page, -+ d->hDPI, -+ d->vDPI, -+ d->rotate, -+ false, -+ true, -+ isPrinting, -+ NULL, -+ NULL, -+ annotDisplayDecideCbk, -+ &showAnnotations, true); -+ if (d->pageConvertedCallback) -+ (*d->pageConvertedCallback)(page, d->pageConvertedPayload); -+ } -+ delete psOut; -+ d->closeDevice(); -+ return true; -+ } -+ else -+ { -+ delete psOut; -+ d->closeDevice(); -+ return false; -+ } -+} -+ -+} -diff --git a/qt4/src/poppler-qiodeviceoutstream-private.h b/qt4/src/poppler-qiodeviceoutstream-private.h -new file mode 100644 -index 00000000..d0d20073 ---- /dev/null -+++ b/qt4/src/poppler-qiodeviceoutstream-private.h -@@ -0,0 +1,47 @@ -+/* poppler-qiodevicestream-private.h: Qt4 interface to poppler -+ * Copyright (C) 2008, Pino Toscano -+ * Copyright (C) 2013 Adrian Johnson -+ * -+ * 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_QIODEVICESTREAM_PRIVATE_H -+#define POPPLER_QIODEVICESTREAM_PRIVATE_H -+ -+#include "Object.h" -+#include "Stream.h" -+ -+class QIODevice; -+ -+namespace Poppler { -+ -+class QIODeviceOutStream : public OutStream -+{ -+ public: -+ QIODeviceOutStream(QIODevice* device); -+ virtual ~QIODeviceOutStream(); -+ -+ virtual void close(); -+ virtual Goffset getPos(); -+ virtual void put(char c); -+ virtual void printf(const char *format, ...); -+ -+ private: -+ QIODevice *m_device; -+}; -+ -+} -+ -+#endif -diff --git a/qt4/src/poppler-qiodeviceoutstream.cc b/qt4/src/poppler-qiodeviceoutstream.cc -new file mode 100644 -index 00000000..e3e9f895 ---- /dev/null -+++ b/qt4/src/poppler-qiodeviceoutstream.cc -@@ -0,0 +1,64 @@ -+/* poppler-qiodevicestream.cc: Qt4 interface to poppler -+ * Copyright (C) 2008, Pino Toscano -+ * Copyright (C) 2013 Adrian Johnson -+ * -+ * 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-qiodeviceoutstream-private.h" -+ -+#include -+ -+#include -+ -+#define QIODeviceOutStreamBufSize 8192 -+ -+namespace Poppler { -+ -+QIODeviceOutStream::QIODeviceOutStream(QIODevice* device) -+ : m_device(device) -+{ -+} -+ -+QIODeviceOutStream::~QIODeviceOutStream() -+{ -+} -+ -+void QIODeviceOutStream::close() -+{ -+} -+ -+Goffset QIODeviceOutStream::getPos() -+{ -+ return m_device->pos(); -+} -+ -+void QIODeviceOutStream::put(char c) -+{ -+ m_device->putChar(c); -+} -+ -+void QIODeviceOutStream::printf(const char *format, ...) -+{ -+ va_list ap; -+ va_start(ap, format); -+ char buf[QIODeviceOutStreamBufSize]; -+ size_t bufsize = 0; -+ bufsize = qvsnprintf(buf, QIODeviceOutStreamBufSize - 1, format, ap); -+ va_end(ap); -+ m_device->write(buf, bufsize); -+} -+ -+} -diff --git a/qt4/src/poppler-qt4.h b/qt4/src/poppler-qt4.h -new file mode 100644 -index 00000000..1b5afb2e ---- /dev/null -+++ b/qt4/src/poppler-qt4.h -@@ -0,0 +1,1990 @@ -+/* poppler-qt.h: qt interface to poppler -+ * Copyright (C) 2005, Net Integration Technologies, Inc. -+ * Copyright (C) 2005, 2007, Brad Hards -+ * Copyright (C) 2005-2012, 2014, 2015, Albert Astals Cid -+ * Copyright (C) 2005, Stefan Kebekus -+ * Copyright (C) 2006-2011, Pino Toscano -+ * Copyright (C) 2009 Shawn Rutledge -+ * Copyright (C) 2010 Suzuki Toshiya -+ * Copyright (C) 2010 Matthias Fauconneau -+ * Copyright (C) 2011 Andreas Hartmetz -+ * Copyright (C) 2011 Glad Deschrijver -+ * Copyright (C) 2012, Guillermo A. Amaral B. -+ * Copyright (C) 2012, Fabio D'Urso -+ * Copyright (C) 2012, Tobias Koenig -+ * Copyright (C) 2012, 2014, 2015 Adam Reichold -+ * Copyright (C) 2012, 2013 Thomas Freitag -+ * Copyright (C) 2016 Jakub Alba -+ * -+ * 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_QT_H__ -+#define __POPPLER_QT_H__ -+ -+#include "poppler-annotation.h" -+#include "poppler-link.h" -+#include "poppler-optcontent.h" -+#include "poppler-page-transition.h" -+ -+#include -+#include -+#include -+#include -+#include "poppler-export.h" -+ -+class EmbFile; -+class Sound; -+class AnnotMovie; -+ -+/** -+ The %Poppler Qt4 binding. -+*/ -+namespace Poppler { -+ -+ class Document; -+ class DocumentData; -+ -+ class PageData; -+ -+ class FormField; -+ -+ class TextBoxData; -+ -+ class PDFConverter; -+ class PSConverter; -+ -+ /** -+ Debug/error function. -+ -+ This function type is used for debugging & error output; -+ the first parameter is the actual message, the second is the unaltered -+ closure argument which was passed to the setDebugErrorFunction call. -+ -+ \since 0.16 -+ */ -+ typedef void (*PopplerDebugFunc)(const QString & /*message*/, const QVariant & /*closure*/); -+ -+ /** -+ Set a new debug/error output function. -+ -+ If not set, by default error and debug messages will be sent to the -+ Qt \p qDebug() function. -+ -+ \param debugFunction the new debug function -+ \param closure user data which will be passes as-is to the debug function -+ -+ \since 0.16 -+ */ -+ POPPLER_QT4_EXPORT void setDebugErrorFunction(PopplerDebugFunc debugFunction, const QVariant &closure); -+ -+ /** -+ Describes the physical location of text on a document page -+ -+ This very simple class describes the physical location of text -+ on the page. It consists of -+ - a QString that contains the text -+ - a QRectF that gives a box that describes where on the page -+ the text is found. -+ */ -+ class POPPLER_QT4_EXPORT TextBox { -+ friend class Page; -+ public: -+ /** -+ The default constructor sets the \p text and the rectangle that -+ contains the text. Coordinates for the \p bBox are in points = -+ 1/72 of an inch. -+ */ -+ TextBox(const QString& text, const QRectF &bBox); -+ /** -+ Destructor. -+ */ -+ ~TextBox(); -+ -+ /** -+ Returns the text of this text box -+ */ -+ QString text() const; -+ -+ /** -+ Returns the position of the text, in point, i.e., 1/72 of -+ an inch -+ -+ \since 0.8 -+ */ -+ QRectF boundingBox() const; -+ -+ /** -+ Returns the pointer to the next text box, if there is one. -+ -+ Otherwise, it returns a null pointer. -+ */ -+ TextBox *nextWord() const; -+ -+ /** -+ Returns the bounding box of the \p i -th characted of the word. -+ */ -+ QRectF charBoundingBox(int i) const; -+ -+ /** -+ Returns whether there is a space character after this text box -+ */ -+ bool hasSpaceAfter() const; -+ -+ private: -+ Q_DISABLE_COPY(TextBox) -+ -+ TextBoxData *m_data; -+ }; -+ -+ -+ class FontInfoData; -+ /** -+ Container class for information about a font within a PDF -+ document -+ */ -+ class POPPLER_QT4_EXPORT FontInfo { -+ friend class Document; -+ public: -+ /** -+ The type of font. -+ */ -+ enum Type { -+ unknown, -+ Type1, -+ Type1C, -+ Type1COT, -+ Type3, -+ TrueType, -+ TrueTypeOT, -+ CIDType0, -+ CIDType0C, -+ CIDType0COT, -+ CIDTrueType, -+ CIDTrueTypeOT -+ }; -+ -+ /// \cond PRIVATE -+ /** -+ Create a new font information container. -+ */ -+ FontInfo(); -+ -+ /** -+ Create a new font information container. -+ */ -+ FontInfo( const FontInfoData &fid ); -+ /// \endcond -+ -+ /** -+ Copy constructor. -+ */ -+ FontInfo( const FontInfo &fi ); -+ -+ /** -+ Destructor. -+ */ -+ ~FontInfo(); -+ -+ /** -+ The name of the font. Can be QString::null if the font has no name -+ */ -+ QString name() const; -+ -+ /** -+ The path of the font file used to represent this font on this system, -+ or a null string is the font is embedded -+ */ -+ QString file() const; -+ -+ /** -+ Whether the font is embedded in the file, or not -+ -+ \return true if the font is embedded -+ */ -+ bool isEmbedded() const; -+ -+ /** -+ Whether the font provided is only a subset of the full -+ font or not. This only has meaning if the font is embedded. -+ -+ \return true if the font is only a subset -+ */ -+ bool isSubset() const; -+ -+ /** -+ The type of font encoding -+ -+ \return a enumerated value corresponding to the font encoding used -+ -+ \sa typeName for a string equivalent -+ */ -+ Type type() const; -+ -+ /** -+ The name of the font encoding used -+ -+ \note if you are looking for the name of the font (as opposed to the -+ encoding format used), you probably want name(). -+ -+ \sa type for a enumeration version -+ */ -+ QString typeName() const; -+ -+ /** -+ Standard assignment operator -+ */ -+ FontInfo& operator=( const FontInfo &fi ); -+ -+ private: -+ FontInfoData *m_data; -+ }; -+ -+ -+ class FontIteratorData; -+ /** -+ Iterator for reading the fonts in a document. -+ -+ FontIterator provides a Java-style iterator for reading the fonts in a -+ document. -+ -+ You can use it in the following way: -+ \code -+Poppler::FontIterator* it = doc->newFontIterator(); -+while (it->hasNext()) { -+ QList fonts = it->next(); -+ // do something with the fonts -+} -+// after doing the job, the iterator must be freed -+delete it; -+ \endcode -+ -+ \since 0.12 -+ */ -+ class POPPLER_QT4_EXPORT FontIterator { -+ friend class Document; -+ friend class DocumentData; -+ public: -+ /** -+ Destructor. -+ */ -+ ~FontIterator(); -+ -+ /** -+ Returns the fonts of the current page and then advances the iterator -+ to the next page. -+ */ -+ QList next(); -+ -+ /** -+ Checks whether there is at least one more page to iterate, ie returns -+ false when the iterator is beyond the last page. -+ */ -+ bool hasNext() const; -+ -+ /** -+ Returns the current page where the iterator is. -+ */ -+ int currentPage() const; -+ -+ private: -+ Q_DISABLE_COPY( FontIterator ) -+ FontIterator( int, DocumentData *dd ); -+ -+ FontIteratorData *d; -+ }; -+ -+ -+ class EmbeddedFileData; -+ /** -+ Container class for an embedded file with a PDF document -+ */ -+ class POPPLER_QT4_EXPORT EmbeddedFile { -+ friend class DocumentData; -+ friend class AnnotationPrivate; -+ public: -+ /// \cond PRIVATE -+ EmbeddedFile(EmbFile *embfile); -+ /// \endcond -+ -+ /** -+ Destructor. -+ */ -+ ~EmbeddedFile(); -+ -+ /** -+ The name associated with the file -+ */ -+ QString name() const; -+ -+ /** -+ The description associated with the file, if any. -+ -+ This will return an empty QString if there is no description element -+ */ -+ QString description() const; -+ -+ /** -+ The size of the file. -+ -+ This will return < 0 if there is no size element -+ */ -+ int size() const; -+ -+ /** -+ The modification date for the embedded file, if known. -+ */ -+ QDateTime modDate() const; -+ -+ /** -+ The creation date for the embedded file, if known. -+ */ -+ QDateTime createDate() const; -+ -+ /** -+ The MD5 checksum of the file. -+ -+ This will return an empty QByteArray if there is no checksum element. -+ */ -+ QByteArray checksum() const; -+ -+ /** -+ The MIME type of the file, if known. -+ -+ \since 0.8 -+ */ -+ QString mimeType() const; -+ -+ /** -+ The data as a byte array -+ */ -+ QByteArray data(); -+ -+ /** -+ Is the embedded file valid? -+ -+ \since 0.12 -+ */ -+ bool isValid() const; -+ -+ /** -+ A QDataStream for the actual data? -+ */ -+ //QDataStream dataStream() const; -+ -+ private: -+ Q_DISABLE_COPY(EmbeddedFile) -+ EmbeddedFile(EmbeddedFileData &dd); -+ -+ EmbeddedFileData *m_embeddedFile; -+ }; -+ -+ -+ /** -+ \brief A page in a document. -+ -+ The Page class represents a single page within a PDF document. -+ -+ You cannot construct a Page directly, but you have to use the Document -+ functions that return a new Page out of an index or a label. -+ */ -+ class POPPLER_QT4_EXPORT Page { -+ friend class Document; -+ public: -+ /** -+ Destructor. -+ */ -+ ~Page(); -+ -+ /** -+ The type of rotation to apply for an operation -+ */ -+ enum Rotation { Rotate0 = 0, ///< Do not rotate -+ Rotate90 = 1, ///< Rotate 90 degrees clockwise -+ Rotate180 = 2, ///< Rotate 180 degrees -+ Rotate270 = 3 ///< Rotate 270 degrees clockwise (90 degrees counterclockwise) -+ }; -+ -+ /** -+ The kinds of page actions -+ */ -+ enum PageAction { -+ Opening, ///< The action when a page is "opened" -+ Closing ///< The action when a page is "closed" -+ }; -+ -+ /** -+ How the text is going to be returned -+ \since 0.16 -+ */ -+ enum TextLayout { -+ PhysicalLayout, ///< The text is layouted to resemble the real page layout -+ RawOrderLayout ///< The text is returned without any type of processing -+ }; -+ -+ /** -+ Additional flags for the renderToPainter method -+ \since 0.16 -+ */ -+ enum PainterFlag { -+ /** -+ Do not save/restore the caller-owned painter. -+ -+ renderToPainter() by default preserves, using save() + restore(), -+ the state of the painter specified; if this is not needed, this -+ flag can avoid this job -+ */ -+ DontSaveAndRestore = 0x00000001 -+ }; -+ Q_DECLARE_FLAGS( PainterFlags, PainterFlag ) -+ -+ /** -+ Render the page to a QImage using the current -+ \link Document::renderBackend() Document renderer\endlink. -+ -+ If \p x = \p y = \p w = \p h = -1, the method will automatically -+ compute the size of the image from the horizontal and vertical -+ resolutions specified in \p xres and \p yres. Otherwise, the -+ method renders only a part of the page, specified by the -+ parameters (\p x, \p y, \p w, \p h) in pixel coordinates. The returned -+ QImage then has size (\p w, \p h), independent of the page -+ size. -+ -+ \param x specifies the left x-coordinate of the box, in -+ pixels. -+ -+ \param y specifies the top y-coordinate of the box, in -+ pixels. -+ -+ \param w specifies the width of the box, in pixels. -+ -+ \param h specifies the height of the box, in pixels. -+ -+ \param xres horizontal resolution of the graphics device, -+ in dots per inch -+ -+ \param yres vertical resolution of the graphics device, in -+ dots per inch -+ -+ \param rotate how to rotate the page -+ -+ \warning The parameter (\p x, \p y, \p w, \p h) are not -+ well-tested. Unusual or meaningless parameters may lead to -+ rather unexpected results. -+ -+ \returns a QImage of the page, or a null image on failure. -+ -+ \since 0.6 -+ */ -+ QImage renderToImage(double xres=72.0, double yres=72.0, int x=-1, int y=-1, int w=-1, int h=-1, Rotation rotate = Rotate0) const; -+ -+ /** -+ Render the page to the specified QPainter using the current -+ \link Document::renderBackend() Document renderer\endlink. -+ -+ If \p x = \p y = \p w = \p h = -1, the method will automatically -+ compute the size of the page area from the horizontal and vertical -+ resolutions specified in \p xres and \p yres. Otherwise, the -+ method renders only a part of the page, specified by the -+ parameters (\p x, \p y, \p w, \p h) in pixel coordinates. -+ -+ \param painter the painter to paint on -+ -+ \param x specifies the left x-coordinate of the box, in -+ pixels. -+ -+ \param y specifies the top y-coordinate of the box, in -+ pixels. -+ -+ \param w specifies the width of the box, in pixels. -+ -+ \param h specifies the height of the box, in pixels. -+ -+ \param xres horizontal resolution of the graphics device, -+ in dots per inch -+ -+ \param yres vertical resolution of the graphics device, in -+ dots per inch -+ -+ \param rotate how to rotate the page -+ -+ \param flags additional painter flags -+ -+ \warning The parameter (\p x, \p y, \p w, \p h) are not -+ well-tested. Unusual or meaningless parameters may lead to -+ rather unexpected results. -+ -+ \returns whether the painting succeeded -+ -+ \note This method is only supported for Arthur -+ -+ \since 0.16 -+ */ -+ bool renderToPainter(QPainter* painter, double xres=72.0, double yres=72.0, int x=-1, int y=-1, int w=-1, int h=-1, -+ Rotation rotate = Rotate0, PainterFlags flags = 0) const; -+ -+ /** -+ Get the page thumbnail if it exists. -+ -+ \return a QImage of the thumbnail, or a null image -+ if the PDF does not contain one for this page -+ -+ \since 0.12 -+ */ -+ QImage thumbnail() const; -+ -+ /** -+ Returns the text that is inside a specified rectangle -+ -+ \param rect the rectangle specifying the area of interest, -+ with coordinates given in points, i.e., 1/72th of an inch. -+ If rect is null, all text on the page is given -+ -+ \since 0.16 -+ **/ -+ QString text(const QRectF &rect, TextLayout textLayout) const; -+ -+ /** -+ Returns the text that is inside a specified rectangle. -+ The text is returned using the physical layout of the page -+ -+ \param rect the rectangle specifying the area of interest, -+ with coordinates given in points, i.e., 1/72th of an inch. -+ If rect is null, all text on the page is given -+ **/ -+ QString text(const QRectF &rect) const; -+ -+ /** -+ The starting point for a search -+ */ -+ enum SearchDirection { FromTop, ///< Start sorting at the top of the document -+ NextResult, ///< Find the next result, moving "down the page" -+ PreviousResult ///< Find the previous result, moving "up the page" -+ }; -+ -+ /** -+ The type of search to perform -+ */ -+ enum SearchMode { CaseSensitive, ///< Case differences cause no match in searching -+ CaseInsensitive ///< Case differences are ignored in matching -+ }; -+ -+ /** -+ Flags to modify the search behaviour \since 0.31 -+ */ -+ enum SearchFlag -+ { -+ IgnoreCase = 0x00000001, ///< Case differences are ignored -+ WholeWords = 0x00000002 ///< Only whole words are matched -+ }; -+ Q_DECLARE_FLAGS( SearchFlags, SearchFlag ) -+ -+ /** -+ Returns true if the specified text was found. -+ -+ \param text the text the search -+ \param rect in all directions is used to return where the text was found, for NextResult and PreviousResult -+ indicates where to continue searching for -+ \param direction in which direction do the search -+ \param caseSensitive be case sensitive? -+ \param rotate the rotation to apply for the search order -+ **/ -+ Q_DECL_DEPRECATED bool search(const QString &text, QRectF &rect, SearchDirection direction, SearchMode caseSensitive, Rotation rotate = Rotate0) const; -+ -+ /** -+ Returns true if the specified text was found. -+ -+ \param text the text the search -+ \param rectXXX in all directions is used to return where the text was found, for NextResult and PreviousResult -+ indicates where to continue searching for -+ \param direction in which direction do the search -+ \param caseSensitive be case sensitive? -+ \param rotate the rotation to apply for the search order -+ \since 0.14 -+ **/ -+ Q_DECL_DEPRECATED bool search(const QString &text, double &rectLeft, double &rectTop, double &rectRight, double &rectBottom, SearchDirection direction, SearchMode caseSensitive, Rotation rotate = Rotate0) const; -+ -+ /** -+ Returns true if the specified text was found. -+ -+ \param text the text the search -+ \param rectXXX in all directions is used to return where the text was found, for NextResult and PreviousResult -+ indicates where to continue searching for -+ \param direction in which direction do the search -+ \param flags the flags to consider during matching -+ \param rotate the rotation to apply for the search order -+ -+ \since 0.31 -+ **/ -+ bool search(const QString &text, double &rectLeft, double &rectTop, double &rectRight, double &rectBottom, SearchDirection direction, SearchFlags flags = 0, Rotation rotate = Rotate0) const; -+ -+ /** -+ Returns a list of all occurrences of the specified text on the page. -+ -+ \param text the text to search -+ \param caseSensitive whether to be case sensitive -+ \param rotate the rotation to apply for the search order -+ -+ \warning Do not use the returned QRectF as arguments of another search call because of truncation issues if qreal is defined as float. -+ -+ \since 0.22 -+ **/ -+ Q_DECL_DEPRECATED QList search(const QString &text, SearchMode caseSensitive, Rotation rotate = Rotate0) const; -+ -+ /** -+ Returns a list of all occurrences of the specified text on the page. -+ -+ \param text the text to search -+ \param flags the flags to consider during matching -+ \param rotate the rotation to apply for the search order -+ -+ \warning Do not use the returned QRectF as arguments of another search call because of truncation issues if qreal is defined as float. -+ -+ \since 0.31 -+ **/ -+ QList search(const QString &text, SearchFlags flags = 0, Rotation rotate = Rotate0) const; -+ -+ /** -+ Returns a list of text of the page -+ -+ This method returns a QList of TextBoxes that contain all -+ the text of the page, with roughly one text word of text -+ per TextBox item. -+ -+ For text written in western languages (left-to-right and -+ up-to-down), the QList contains the text in the proper -+ order. -+ -+ \note The caller owns the text boxes and they should -+ be deleted when no longer required. -+ -+ \warning This method is not tested with Asian scripts -+ */ -+ QList textList(Rotation rotate = Rotate0) const; -+ -+ /** -+ \return The dimensions (cropbox) of the page, in points (i.e. 1/72th of an inch) -+ */ -+ QSizeF pageSizeF() const; -+ -+ /** -+ \return The dimensions (cropbox) of the page, in points (i.e. 1/72th of an inch) -+ */ -+ QSize pageSize() const; -+ -+ /** -+ Returns the transition of this page -+ -+ \returns a pointer to a PageTransition structure that -+ defines how transition to this page shall be performed. -+ -+ \note The PageTransition structure is owned by this page, and will -+ automatically be destroyed when this page class is -+ destroyed. -+ **/ -+ PageTransition *transition() const; -+ -+ /** -+ Gets the page action specified, or NULL if there is no action. -+ -+ \since 0.6 -+ **/ -+ Link *action( PageAction act ) const; -+ -+ /** -+ Types of orientations that are possible -+ */ -+ enum Orientation { -+ Landscape, ///< Landscape orientation (portrait, with 90 degrees clockwise rotation ) -+ Portrait, ///< Normal portrait orientation -+ Seascape, ///< Seascape orientation (portrait, with 270 degrees clockwise rotation) -+ UpsideDown ///< Upside down orientation (portrait, with 180 degrees rotation) -+ }; -+ -+ /** -+ The orientation of the page -+ */ -+ Orientation orientation() const; -+ -+ /** -+ The default CTM -+ */ -+ void defaultCTM(double *CTM, double dpiX, double dpiY, int rotate, bool upsideDown); -+ -+ /** -+ Gets the links of the page -+ */ -+ QList links() const; -+ -+ /** -+ Returns the annotations of the page -+ -+ \note If you call this method twice, you get different objects -+ pointing to the same annotations (see Annotation). -+ The caller owns the returned objects and they should be deleted -+ when no longer required. -+ */ -+ QList annotations() const; -+ -+ /** -+ Returns the annotations of the page -+ -+ \param subtypes the subtypes of annotations you are interested in -+ -+ \note If you call this method twice, you get different objects -+ pointing to the same annotations (see Annotation). -+ The caller owns the returned objects and they should be deleted -+ when no longer required. -+ -+ \since 0.28 -+ */ -+ QList annotations(const QSet &subtypes) const; -+ -+ /** -+ Adds an annotation to the page -+ -+ \note Ownership of the annotation object stays with the caller, who can -+ delete it at any time. -+ \since 0.20 -+ */ -+ void addAnnotation( const Annotation *ann ); -+ -+ /** -+ Removes an annotation from the page and destroys the annotation object -+ -+ \note There mustn't be other Annotation objects pointing this annotation -+ \since 0.20 -+ */ -+ void removeAnnotation( const Annotation *ann ); -+ -+ /** -+ Returns the form fields on the page -+ The caller gets the ownership of the returned objects. -+ -+ \since 0.6 -+ */ -+ QList formFields() const; -+ -+ /** -+ Returns the page duration. That is the time, in seconds, that the page -+ should be displayed before the presentation automatically advances to the next page. -+ Returns < 0 if duration is not set. -+ -+ \since 0.6 -+ */ -+ double duration() const; -+ -+ /** -+ Returns the label of the page, or a null string is the page has no label. -+ -+ \since 0.6 -+ **/ -+ QString label() const; -+ -+ private: -+ Q_DISABLE_COPY(Page) -+ -+ Page(DocumentData *doc, int index); -+ PageData *m_page; -+ }; -+ -+/** -+ \brief PDF document. -+ -+ The Document class represents a PDF document: its pages, and all the global -+ properties, metadata, etc. -+ -+ \section ownership Ownership of the returned objects -+ -+ All the functions that returns class pointers create new object, and the -+ responsability of those is given to the callee. -+ -+ The only exception is \link Poppler::Page::transition() Page::transition()\endlink. -+ -+ \section document-loading Loading -+ -+ To get a Document, you have to load it via the load() & loadFromData() -+ functions. -+ -+ In all the functions that have passwords as arguments, they \b must be Latin1 -+ encoded. If you have a password that is a UTF-8 string, you need to use -+ QString::toLatin1() (or similar) to convert the password first. -+ If you have a UTF-8 character array, consider converting it to a QString first -+ (QString::fromUtf8(), or similar) before converting to Latin1 encoding. -+ -+ \section document-rendering Rendering -+ -+ To render pages of a document, you have different Document functions to set -+ various options. -+ -+ \subsection document-rendering-backend Backends -+ -+ %Poppler offers a different backends for rendering the pages. Currently -+ there are two backends (see #RenderBackend), but only the Splash engine works -+ well and has been tested. -+ -+ The available rendering backends can be discovered via availableRenderBackends(). -+ The current rendering backend can be changed using setRenderBackend(). -+ Please note that setting a backend not listed in the available ones -+ will always result in null QImage's. -+ -+ \section document-cms Color management support -+ -+ %Poppler, if compiled with this support, provides functions to handle color -+ profiles. -+ -+ To know whether the %Poppler version you are using has support for color -+ management, you can query Poppler::isCmsAvailable(). In case it is not -+ avilable, all the color management-related functions will either do nothing -+ or return null. -+*/ -+ class POPPLER_QT4_EXPORT Document { -+ friend class Page; -+ friend class DocumentData; -+ -+ public: -+ /** -+ The page mode -+ */ -+ enum PageMode { -+ UseNone, ///< No mode - neither document outline nor thumbnail images are visible -+ UseOutlines, ///< Document outline visible -+ UseThumbs, ///< Thumbnail images visible -+ FullScreen, ///< Fullscreen mode (no menubar, windows controls etc) -+ UseOC, ///< Optional content group panel visible -+ UseAttach ///< Attachments panel visible -+ }; -+ -+ /** -+ The page layout -+ */ -+ enum PageLayout { -+ NoLayout, ///< Layout not specified -+ SinglePage, ///< Display a single page -+ OneColumn, ///< Display a single column of pages -+ TwoColumnLeft, ///< Display the pages in two columns, with odd-numbered pages on the left -+ TwoColumnRight, ///< Display the pages in two columns, with odd-numbered pages on the right -+ TwoPageLeft, ///< Display the pages two at a time, with odd-numbered pages on the left -+ TwoPageRight ///< Display the pages two at a time, with odd-numbered pages on the right -+ }; -+ -+ /** -+ The render backends available -+ -+ \since 0.6 -+ */ -+ enum RenderBackend { -+ SplashBackend, ///< Splash backend -+ ArthurBackend ///< Arthur (Qt4) backend -+ }; -+ -+ /** -+ The render hints available -+ -+ \since 0.6 -+ */ -+ enum RenderHint { -+ Antialiasing = 0x00000001, ///< Antialiasing for graphics -+ TextAntialiasing = 0x00000002, ///< Antialiasing for text -+ TextHinting = 0x00000004, ///< Hinting for text \since 0.12.1 -+ TextSlightHinting = 0x00000008, ///< Lighter hinting for text when combined with TextHinting \since 0.18 -+ OverprintPreview = 0x00000010, ///< Overprint preview \since 0.22 -+ ThinLineSolid = 0x00000020, ///< Enhance thin lines solid \since 0.24 -+ ThinLineShape = 0x00000040, ///< Enhance thin lines shape. Wins over ThinLineSolid \since 0.24 -+ IgnorePaperColor = 0x00000080 ///< Do not compose with the paper color \since 0.35 -+ }; -+ Q_DECLARE_FLAGS( RenderHints, RenderHint ) -+ -+ /** -+ Form types -+ -+ \since 0.22 -+ */ -+ enum FormType { -+ NoForm, ///< Document doesn't contain forms -+ AcroForm, ///< AcroForm -+ XfaForm ///< Adobe XML Forms Architecture (XFA), currently unsupported -+ }; -+ -+ /** -+ Set a color display profile for the current document. -+ -+ \param outputProfileA is a \c cmsHPROFILE of the LCMS library. -+ -+ \since 0.12 -+ */ -+ void setColorDisplayProfile(void *outputProfileA); -+ /** -+ Set a color display profile for the current document. -+ -+ \param name is the name of the display profile to set. -+ -+ \since 0.12 -+ */ -+ void setColorDisplayProfileName(const QString &name); -+ /** -+ Return the current RGB profile. -+ -+ \return a \c cmsHPROFILE of the LCMS library. -+ -+ \since 0.12 -+ */ -+ void* colorRgbProfile() const; -+ /** -+ Return the current display profile. -+ -+ \return a \c cmsHPROFILE of the LCMS library. -+ -+ \since 0.12 -+ */ -+ void *colorDisplayProfile() const; -+ -+ /** -+ Load the document from a file on disk -+ -+ \param filePath the name (and path, if required) of the file to load -+ \param ownerPassword the Latin1-encoded owner password to use in -+ loading the file -+ \param userPassword the Latin1-encoded user ("open") password -+ to use in loading the file -+ -+ \return the loaded document, or NULL on error -+ -+ \note The caller owns the pointer to Document, and this should -+ be deleted when no longer required. -+ -+ \warning The returning document may be locked if a password is required -+ to open the file, and one is not provided (as the userPassword). -+ */ -+ static Document *load(const QString & filePath, -+ const QByteArray &ownerPassword=QByteArray(), -+ const QByteArray &userPassword=QByteArray()); -+ -+ /** -+ Load the document from memory -+ -+ \param fileContents the file contents. They are copied so there is no need -+ to keep the byte array around for the full life time of -+ the document. -+ \param ownerPassword the Latin1-encoded owner password to use in -+ loading the file -+ \param userPassword the Latin1-encoded user ("open") password -+ to use in loading the file -+ -+ \return the loaded document, or NULL on error -+ -+ \note The caller owns the pointer to Document, and this should -+ be deleted when no longer required. -+ -+ \warning The returning document may be locked if a password is required -+ to open the file, and one is not provided (as the userPassword). -+ -+ \since 0.6 -+ */ -+ static Document *loadFromData(const QByteArray &fileContents, -+ const QByteArray &ownerPassword=QByteArray(), -+ const QByteArray &userPassword=QByteArray()); -+ -+ /** -+ Get a specified Page -+ -+ Note that this follows the PDF standard of being zero based - if you -+ want the first page, then you need an index of zero. -+ -+ The caller gets the ownership of the returned object. -+ -+ \param index the page number index -+ */ -+ Page *page(int index) const; -+ -+ /** -+ \overload -+ -+ -+ The intent is that you can pass in a label like \c "ix" and -+ get the page with that label (which might be in the table of -+ contents), or pass in \c "1" and get the page that the user -+ expects (which might not be the first page, if there is a -+ title page and a table of contents). -+ -+ \param label the page label -+ */ -+ Page *page(const QString &label) const; -+ -+ /** -+ The number of pages in the document -+ */ -+ int numPages() const; -+ -+ /** -+ The type of mode that should be used by the application -+ when the document is opened. Note that while this is -+ called page mode, it is really viewer application mode. -+ */ -+ PageMode pageMode() const; -+ -+ /** -+ The layout that pages should be shown in when the document -+ is first opened. This basically describes how pages are -+ shown relative to each other. -+ */ -+ PageLayout pageLayout() const; -+ -+ /** -+ The predominant reading order for text as supplied by -+ the document's viewer preferences. -+ -+ \since 0.26 -+ */ -+ Qt::LayoutDirection textDirection() const; -+ -+ /** -+ Provide the passwords required to unlock the document -+ -+ \param ownerPassword the Latin1-encoded owner password to use in -+ loading the file -+ \param userPassword the Latin1-encoded user ("open") password -+ to use in loading the file -+ */ -+ bool unlock(const QByteArray &ownerPassword, const QByteArray &userPassword); -+ -+ /** -+ Determine if the document is locked -+ */ -+ bool isLocked() const; -+ -+ /** -+ The date associated with the document -+ -+ You would use this method with something like: -+ \code -+QDateTime created = m_doc->date("CreationDate"); -+QDateTime modified = m_doc->date("ModDate"); -+ \endcode -+ -+ The available dates are: -+ - CreationDate: the date of creation of the document -+ - ModDate: the date of the last change in the document -+ -+ \param data the type of date that is required -+ */ -+ QDateTime date( const QString & data ) const; -+ -+ /** -+ Set the Info dict date entry specified by \param key to \param val -+ -+ \returns true on success, false on failure -+ */ -+ bool setDate( const QString & key, const QDateTime & val ); -+ -+ /** -+ The date of the creation of the document -+ */ -+ QDateTime creationDate() const; -+ -+ /** -+ Set the creation date of the document to \param val -+ -+ \returns true on success, false on failure -+ */ -+ bool setCreationDate( const QDateTime & val ); -+ -+ /** -+ The date of the last change in the document -+ */ -+ QDateTime modificationDate() const; -+ -+ /** -+ Set the modification date of the document to \param val -+ -+ \returns true on success, false on failure -+ */ -+ bool setModificationDate( const QDateTime & val ); -+ -+ /** -+ Get specified information associated with the document -+ -+ You would use this method with something like: -+ \code -+QString title = m_doc->info("Title"); -+QString subject = m_doc->info("Subject"); -+ \endcode -+ -+ In addition to \c Title and \c Subject, other information that may -+ be available include \c Author, \c Keywords, \c Creator and \c Producer. -+ -+ \param data the information that is required -+ -+ \sa infoKeys() to get a list of the available keys -+ */ -+ QString info( const QString & data ) const; -+ -+ /** -+ Set the value of the document's Info dictionary entry specified by \param key to \param val -+ -+ \returns true on success, false on failure -+ */ -+ bool setInfo( const QString & key, const QString & val ); -+ -+ /** -+ The title of the document -+ */ -+ QString title() const; -+ -+ /** -+ Set the title of the document to \param val -+ -+ \returns true on success, false on failure -+ */ -+ bool setTitle( const QString & val ); -+ -+ /** -+ The author of the document -+ */ -+ QString author() const; -+ -+ /** -+ Set the author of the document to \param val -+ -+ \returns true on success, false on failure -+ */ -+ bool setAuthor( const QString & val ); -+ -+ /** -+ The subject of the document -+ */ -+ QString subject() const; -+ -+ /** -+ Set the subject of the document to \param val -+ -+ \returns true on success, false on failure -+ */ -+ bool setSubject( const QString & val ); -+ -+ /** -+ The keywords of the document -+ */ -+ QString keywords() const; -+ -+ /** -+ Set the keywords of the document to \param val -+ -+ \returns true on success, false on failure -+ */ -+ bool setKeywords( const QString & val ); -+ -+ /** -+ The creator of the document -+ */ -+ QString creator() const; -+ -+ /** -+ Set the creator of the document to \param val -+ -+ \returns true on success, false on failure -+ */ -+ bool setCreator( const QString & val ); -+ -+ /** -+ The producer of the document -+ */ -+ QString producer() const; -+ -+ /** -+ Set the producer of the document to \param val -+ -+ \returns true on success, false on failure -+ */ -+ bool setProducer( const QString & val ); -+ -+ /** -+ Remove the document's Info dictionary -+ -+ \returns true on success, false on failure -+ */ -+ bool removeInfo(); -+ -+ /** -+ Obtain a list of the available string information keys. -+ */ -+ QStringList infoKeys() const; -+ -+ /** -+ Test if the document is encrypted -+ */ -+ bool isEncrypted() const; -+ -+ /** -+ Test if the document is linearised -+ -+ In some cases, this is called "fast web view", since it -+ is mostly an optimisation for viewing over the Web. -+ */ -+ bool isLinearized() const; -+ -+ /** -+ Test if the permissions on the document allow it to be -+ printed -+ */ -+ bool okToPrint() const; -+ -+ /** -+ Test if the permissions on the document allow it to be -+ printed at high resolution -+ */ -+ bool okToPrintHighRes() const; -+ -+ /** -+ Test if the permissions on the document allow it to be -+ changed. -+ -+ \note depending on the type of change, it may be more -+ appropriate to check other properties as well. -+ */ -+ bool okToChange() const; -+ -+ /** -+ Test if the permissions on the document allow the -+ contents to be copied / extracted -+ */ -+ bool okToCopy() const; -+ -+ /** -+ Test if the permissions on the document allow annotations -+ to be added or modified, and interactive form fields (including -+ signature fields) to be completed. -+ */ -+ bool okToAddNotes() const; -+ -+ /** -+ Test if the permissions on the document allow interactive -+ form fields (including signature fields) to be completed. -+ -+ \note this can be true even if okToAddNotes() is false - this -+ means that only form completion is permitted. -+ */ -+ bool okToFillForm() const; -+ -+ /** -+ Test if the permissions on the document allow interactive -+ form fields (including signature fields) to be set, created and -+ modified -+ */ -+ bool okToCreateFormFields() const; -+ -+ /** -+ Test if the permissions on the document allow content extraction -+ (text and perhaps other content) for accessibility usage (eg for -+ a screen reader) -+ */ -+ bool okToExtractForAccessibility() const; -+ -+ /** -+ Test if the permissions on the document allow it to be -+ "assembled" - insertion, rotation and deletion of pages; -+ or creation of bookmarks and thumbnail images. -+ -+ \note this can be true even if okToChange() is false -+ */ -+ bool okToAssemble() const; -+ -+ /** -+ The version of the PDF specification that the document -+ conforms to -+ -+ \deprecated use getPdfVersion and avoid float point -+ comparisons/handling -+ */ -+ Q_DECL_DEPRECATED double pdfVersion() const; -+ -+ /** -+ The version of the PDF specification that the document -+ conforms to -+ -+ \param major an optional pointer to a variable where store the -+ "major" number of the version -+ \param minor an optional pointer to a variable where store the -+ "minor" number of the version -+ -+ \since 0.12 -+ */ -+ void getPdfVersion(int *major, int *minor) const; -+ -+ /** -+ The fonts within the PDF document. -+ -+ This is a shorthand for getting all the fonts at once. -+ -+ \note this can take a very long time to run with a large -+ document. You may wish to use a FontIterator if you have more -+ than say 20 pages -+ -+ \see newFontIterator() -+ */ -+ QList fonts() const; -+ -+ /** -+ Scans for fonts within the PDF document. -+ -+ \param numPages the number of pages to scan -+ \param fontList pointer to the list where the font information -+ should be placed -+ -+ \note with this method you can scan for fonts only \em once for each -+ document; once the end is reached, no more scanning with this method -+ can be done -+ -+ \return false if the end of the document has been reached -+ -+ \deprecated this function is quite limited in its job (see note), -+ better use fonts() or newFontIterator() -+ -+ \see fonts(), newFontIterator() -+ */ -+ Q_DECL_DEPRECATED bool scanForFonts( int numPages, QList *fontList ) const; -+ -+ /** -+ Creates a new FontIterator object for font scanning. -+ -+ The new iterator can be used for reading the font information of the -+ document, reading page by page. -+ -+ The caller is responsible for the returned object, ie it should freed -+ it when no more useful. -+ -+ \param startPage the initial page from which start reading fonts -+ -+ \see fonts() -+ -+ \since 0.12 -+ */ -+ FontIterator* newFontIterator( int startPage = 0 ) const; -+ -+ /** -+ The font data if the font is an embedded one. -+ -+ \since 0.10 -+ */ -+ QByteArray fontData(const FontInfo &font) const; -+ -+ /** -+ The documents embedded within the PDF document. -+ -+ \note there are two types of embedded document - this call -+ only accesses documents that are embedded at the document level. -+ */ -+ QList embeddedFiles() const; -+ -+ /** -+ Whether there are any documents embedded in this PDF document. -+ */ -+ bool hasEmbeddedFiles() const; -+ -+ /** -+ Gets the table of contents (TOC) of the Document. -+ -+ The caller is responsable for the returned object. -+ -+ In the tree the tag name is the 'screen' name of the entry. A tag can have -+ attributes. Here follows the list of tag attributes with meaning: -+ - Destination: A string description of the referred destination -+ - DestinationName: A 'named reference' to the viewport -+ - ExternalFileName: A link to a external filename -+ - Open: A bool value that tells whether the subbranch of the item is open or not -+ -+ Resolving the final destination for each item can be done in the following way: -+ - first, checking for 'Destination': if not empty, then a LinkDestination -+ can be constructed straight with it -+ - as second step, if the 'DestinationName' is not empty, then the destination -+ can be resolved using linkDestination() -+ -+ Note also that if 'ExternalFileName' is not emtpy, then the destination refers -+ to that document (and not to the current one). -+ -+ \returns the TOC, or NULL if the Document does not have one -+ */ -+ QDomDocument *toc() const; -+ -+ /** -+ Tries to resolve the named destination \p name. -+ -+ \note this operation starts a search through the whole document -+ -+ \returns a new LinkDestination object if the named destination was -+ actually found, or NULL otherwise -+ */ -+ LinkDestination *linkDestination( const QString &name ); -+ -+ /** -+ Sets the paper color -+ -+ \param color the new paper color -+ */ -+ void setPaperColor(const QColor &color); -+ /** -+ The paper color -+ -+ The default color is white. -+ */ -+ QColor paperColor() const; -+ -+ /** -+ Sets the backend used to render the pages. -+ -+ \param backend the new rendering backend -+ -+ \since 0.6 -+ */ -+ void setRenderBackend( RenderBackend backend ); -+ /** -+ The currently set render backend -+ -+ The default backend is \ref SplashBackend -+ -+ \since 0.6 -+ */ -+ RenderBackend renderBackend() const; -+ -+ /** -+ The available rendering backends. -+ -+ \since 0.6 -+ */ -+ static QSet availableRenderBackends(); -+ -+ /** -+ Sets the render \p hint . -+ -+ \note some hints may not be supported by some rendering backends. -+ -+ \param on whether the flag should be added or removed. -+ -+ \since 0.6 -+ */ -+ void setRenderHint( RenderHint hint, bool on = true ); -+ /** -+ The currently set render hints. -+ -+ \since 0.6 -+ */ -+ RenderHints renderHints() const; -+ -+ /** -+ Gets a new PS converter for this document. -+ -+ The caller gets the ownership of the returned converter. -+ -+ \since 0.6 -+ */ -+ PSConverter *psConverter() const; -+ -+ /** -+ Gets a new PDF converter for this document. -+ -+ The caller gets the ownership of the returned converter. -+ -+ \since 0.8 -+ */ -+ PDFConverter *pdfConverter() const; -+ -+ /** -+ Gets the metadata stream contents -+ -+ \since 0.6 -+ */ -+ QString metadata() const; -+ -+ /** -+ Test whether this document has "optional content". -+ -+ Optional content is used to optionally turn on (display) -+ and turn off (not display) some elements of the document. -+ The most common use of this is for layers in design -+ applications, but it can be used for a range of things, -+ such as not including some content in printing, and -+ displaying content in the appropriate language. -+ -+ \since 0.8 -+ */ -+ bool hasOptionalContent() const; -+ -+ /** -+ Itemviews model for optional content. -+ -+ The model is owned by the document. -+ -+ \since 0.8 -+ */ -+ OptContentModel *optionalContentModel(); -+ -+ /** -+ Document-level JavaScript scripts. -+ -+ Returns the list of document level JavaScript scripts to be always -+ executed before any other script. -+ -+ \since 0.10 -+ */ -+ QStringList scripts() const; -+ -+ /** -+ The PDF identifiers. -+ -+ \param permanentId an optional pointer to a variable where store the -+ permanent ID of the document -+ \param updateId an optional pointer to a variable where store the -+ update ID of the document -+ -+ \return whether the document has the IDs -+ -+ \since 0.16 -+ */ -+ bool getPdfId(QByteArray *permanentId, QByteArray *updateId) const; -+ -+ /** -+ Returns the type of forms contained in the document -+ -+ \since 0.22 -+ */ -+ FormType formType() const; -+ -+ /** -+ Destructor. -+ */ -+ ~Document(); -+ -+ private: -+ Q_DISABLE_COPY(Document) -+ -+ DocumentData *m_doc; -+ -+ Document(DocumentData *dataA); -+ }; -+ -+ class BaseConverterPrivate; -+ class PSConverterPrivate; -+ class PDFConverterPrivate; -+ /** -+ \brief Base converter. -+ -+ This is the base class for the converters. -+ -+ \since 0.8 -+ */ -+ class POPPLER_QT4_EXPORT BaseConverter -+ { -+ friend class Document; -+ public: -+ /** -+ Destructor. -+ */ -+ virtual ~BaseConverter(); -+ -+ /** Sets the output file name. You must set this or the output device. */ -+ void setOutputFileName(const QString &outputFileName); -+ -+ /** -+ * Sets the output device. You must set this or the output file name. -+ * -+ * \since 0.8 -+ */ -+ void setOutputDevice(QIODevice *device); -+ -+ /** -+ Does the conversion. -+ -+ \return whether the conversion succeeded -+ */ -+ virtual bool convert() = 0; -+ -+ enum Error -+ { -+ NoError, -+ FileLockedError, -+ OpenOutputError, -+ NotSupportedInputFileError -+ }; -+ -+ /** -+ Returns the last error -+ \since 0.12.1 -+ */ -+ Error lastError() const; -+ -+ protected: -+ /// \cond PRIVATE -+ BaseConverter(BaseConverterPrivate &dd); -+ Q_DECLARE_PRIVATE(BaseConverter) -+ BaseConverterPrivate *d_ptr; -+ /// \endcond -+ -+ private: -+ Q_DISABLE_COPY(BaseConverter) -+ }; -+ -+ /** -+ Converts a PDF to PS -+ -+ Sizes have to be in Points (1/72 inch) -+ -+ If you are using QPrinter you can get paper size by doing: -+ \code -+QPrinter dummy(QPrinter::PrinterResolution); -+dummy.setFullPage(true); -+dummy.setPageSize(myPageSize); -+width = dummy.width(); -+height = dummy.height(); -+ \endcode -+ -+ \since 0.6 -+ */ -+ class POPPLER_QT4_EXPORT PSConverter : public BaseConverter -+ { -+ friend class Document; -+ public: -+ /** -+ Options for the PS export. -+ -+ \since 0.10 -+ */ -+ enum PSOption { -+ Printing = 0x00000001, ///< The PS is generated for printing purposes -+ StrictMargins = 0x00000002, -+ ForceRasterization = 0x00000004, -+ PrintToEPS = 0x00000008, ///< Output EPS instead of PS \since 0.20 -+ HideAnnotations = 0x00000010 ///< Don't print annotations \since 0.20 -+ }; -+ Q_DECLARE_FLAGS( PSOptions, PSOption ) -+ -+ /** -+ Destructor. -+ */ -+ ~PSConverter(); -+ -+ /** Sets the list of pages to print. Mandatory. */ -+ void setPageList(const QList &pageList); -+ -+ /** -+ Sets the title of the PS Document. Optional -+ */ -+ void setTitle(const QString &title); -+ -+ /** -+ Sets the horizontal DPI. Defaults to 72.0 -+ */ -+ void setHDPI(double hDPI); -+ -+ /** -+ Sets the vertical DPI. Defaults to 72.0 -+ */ -+ void setVDPI(double vDPI); -+ -+ /** -+ Sets the rotate. Defaults to not rotated -+ */ -+ void setRotate(int rotate); -+ -+ /** -+ Sets the output paper width. Has to be set. -+ */ -+ void setPaperWidth(int paperWidth); -+ -+ /** -+ Sets the output paper height. Has to be set. -+ */ -+ void setPaperHeight(int paperHeight); -+ -+ /** -+ Sets the output right margin. Defaults to 0 -+ */ -+ void setRightMargin(int marginRight); -+ -+ /** -+ Sets the output bottom margin. Defaults to 0 -+ */ -+ void setBottomMargin(int marginBottom); -+ -+ /** -+ Sets the output left margin. Defaults to 0 -+ */ -+ void setLeftMargin(int marginLeft); -+ -+ /** -+ Sets the output top margin. Defaults to 0 -+ */ -+ void setTopMargin(int marginTop); -+ -+ /** -+ Defines if margins have to be strictly followed (even if that -+ means changing aspect ratio), or if the margins can be adapted -+ to keep aspect ratio. -+ -+ Defaults to false. -+ */ -+ void setStrictMargins(bool strictMargins); -+ -+ /** Defines if the page will be rasterized to an image before printing. Defaults to false */ -+ void setForceRasterize(bool forceRasterize); -+ -+ /** -+ Sets the options for the PS export. -+ -+ \since 0.10 -+ */ -+ void setPSOptions(PSOptions options); -+ -+ /** -+ The currently set options for the PS export. -+ -+ The default flags are: Printing. -+ -+ \since 0.10 -+ */ -+ PSOptions psOptions() const; -+ -+ /** -+ Sets a function that will be called each time a page is converted. -+ -+ The payload belongs to the caller. -+ -+ \since 0.16 -+ */ -+ void setPageConvertedCallback(void (* callback)(int page, void *payload), void *payload); -+ -+ bool convert(); -+ -+ private: -+ Q_DECLARE_PRIVATE(PSConverter) -+ Q_DISABLE_COPY(PSConverter) -+ -+ PSConverter(DocumentData *document); -+ }; -+ -+ /** -+ Converts a PDF to PDF (thus saves a copy of the document). -+ -+ \since 0.8 -+ */ -+ class POPPLER_QT4_EXPORT PDFConverter : public BaseConverter -+ { -+ friend class Document; -+ public: -+ /** -+ Options for the PDF export. -+ */ -+ enum PDFOption { -+ WithChanges = 0x00000001 ///< The changes done to the document are saved as well -+ }; -+ Q_DECLARE_FLAGS( PDFOptions, PDFOption ) -+ -+ /** -+ Destructor. -+ */ -+ virtual ~PDFConverter(); -+ -+ /** -+ Sets the options for the PDF export. -+ */ -+ void setPDFOptions(PDFOptions options); -+ /** -+ The currently set options for the PDF export. -+ */ -+ PDFOptions pdfOptions() const; -+ -+ bool convert(); -+ -+ private: -+ Q_DECLARE_PRIVATE(PDFConverter) -+ Q_DISABLE_COPY(PDFConverter) -+ -+ PDFConverter(DocumentData *document); -+ }; -+ -+ /** -+ Conversion from PDF date string format to QDateTime -+ */ -+ POPPLER_QT4_EXPORT QDateTime convertDate( char *dateString ); -+ -+ /** -+ Whether the color management functions are available. -+ -+ \since 0.12 -+ */ -+ POPPLER_QT4_EXPORT bool isCmsAvailable(); -+ -+ /** -+ Whether the overprint preview functionality is available. -+ -+ \since 0.22 -+ */ -+ POPPLER_QT4_EXPORT bool isOverprintPreviewAvailable(); -+ -+ class SoundData; -+ /** -+ Container class for a sound file in a PDF document. -+ -+ A sound can be either External (in that case should be loaded the file -+ whose url is represented by url() ), or Embedded, and the player has to -+ play the data contained in data(). -+ -+ \since 0.6 -+ */ -+ class POPPLER_QT4_EXPORT SoundObject { -+ public: -+ /** -+ The type of sound -+ */ -+ enum SoundType { -+ External, ///< The real sound file is external -+ Embedded ///< The sound is contained in the data -+ }; -+ -+ /** -+ The encoding format used for the sound -+ */ -+ enum SoundEncoding { -+ Raw, ///< Raw encoding, with unspecified or unsigned values in the range [ 0, 2^B - 1 ] -+ Signed, ///< Twos-complement values -+ muLaw, ///< mu-law-encoded samples -+ ALaw ///< A-law-encoded samples -+ }; -+ -+ /// \cond PRIVATE -+ SoundObject(Sound *popplersound); -+ /// \endcond -+ -+ ~SoundObject(); -+ -+ /** -+ Is the sound embedded (SoundObject::Embedded) or external (SoundObject::External)? -+ */ -+ SoundType soundType() const; -+ -+ /** -+ The URL of the sound file to be played, in case of SoundObject::External -+ */ -+ QString url() const; -+ -+ /** -+ The data of the sound, in case of SoundObject::Embedded -+ */ -+ QByteArray data() const; -+ -+ /** -+ The sampling rate of the sound -+ */ -+ double samplingRate() const; -+ -+ /** -+ The number of sound channels to use to play the sound -+ */ -+ int channels() const; -+ -+ /** -+ The number of bits per sample value per channel -+ */ -+ int bitsPerSample() const; -+ -+ /** -+ The encoding used for the sound -+ */ -+ SoundEncoding soundEncoding() const; -+ -+ private: -+ Q_DISABLE_COPY(SoundObject) -+ -+ SoundData *m_soundData; -+ }; -+ -+ class MovieData; -+ /** -+ Container class for a movie object in a PDF document. -+ -+ \since 0.10 -+ */ -+ class POPPLER_QT4_EXPORT MovieObject { -+ friend class AnnotationPrivate; -+ public: -+ /** -+ The play mode for playing the movie -+ */ -+ enum PlayMode { -+ PlayOnce, ///< Play the movie once, closing the movie controls at the end -+ PlayOpen, ///< Like PlayOnce, but leaving the controls open -+ PlayRepeat, ///< Play continuously until stopped -+ PlayPalindrome ///< Play forward, then backward, then again foward and so on until stopped -+ }; -+ -+ ~MovieObject(); -+ -+ /** -+ The URL of the movie to be played -+ */ -+ QString url() const; -+ -+ /** -+ The size of the movie -+ */ -+ QSize size() const; -+ -+ /** -+ The rotation (either 0, 90, 180, or 270 degrees clockwise) for the movie, -+ */ -+ int rotation() const; -+ -+ /** -+ Whether show a bar with movie controls -+ */ -+ bool showControls() const; -+ -+ /** -+ How to play the movie -+ */ -+ PlayMode playMode() const; -+ -+ /** -+ Returns whether a poster image should be shown if the movie is not playing. -+ \since 0.22 -+ */ -+ bool showPosterImage() const; -+ -+ /** -+ Returns the poster image that should be shown if the movie is not playing. -+ If the image is null but showImagePoster() returns @c true, the first frame of the movie -+ should be used as poster image. -+ \since 0.22 -+ */ -+ QImage posterImage() const; -+ -+ private: -+ /// \cond PRIVATE -+ MovieObject( AnnotMovie *ann ); -+ /// \endcond -+ -+ Q_DISABLE_COPY(MovieObject) -+ -+ MovieData *m_movieData; -+ }; -+ -+} -+ -+Q_DECLARE_OPERATORS_FOR_FLAGS(Poppler::Page::PainterFlags) -+Q_DECLARE_OPERATORS_FOR_FLAGS(Poppler::Page::SearchFlags) -+Q_DECLARE_OPERATORS_FOR_FLAGS(Poppler::Document::RenderHints) -+Q_DECLARE_OPERATORS_FOR_FLAGS(Poppler::PDFConverter::PDFOptions) -+Q_DECLARE_OPERATORS_FOR_FLAGS(Poppler::PSConverter::PSOptions) -+ -+#endif -diff --git a/qt4/src/poppler-sound.cc b/qt4/src/poppler-sound.cc -new file mode 100644 -index 00000000..eb19b9d3 ---- /dev/null -+++ b/qt4/src/poppler-sound.cc -@@ -0,0 +1,132 @@ -+/* poppler-sound.cc: qt interface to poppler -+ * Copyright (C) 2006-2007, Pino Toscano -+ * Copyright (C) 2008, Albert Astals Cid -+ * -+ * 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-qt4.h" -+ -+#include "Object.h" -+#include "Stream.h" -+#include "Sound.h" -+ -+namespace Poppler -+{ -+ -+class SoundData -+{ -+public: -+ SoundData() -+ : m_soundObj( 0 ) -+ { -+ } -+ -+ ~SoundData() -+ { -+ delete m_soundObj; -+ } -+ -+ SoundObject::SoundType m_type; -+ Sound *m_soundObj; -+}; -+ -+SoundObject::SoundObject(Sound *popplersound) -+{ -+ m_soundData = new SoundData(); -+ switch ( popplersound->getSoundKind() ) -+ { -+ case soundEmbedded: -+ m_soundData->m_type = SoundObject::Embedded; -+ break; -+ case soundExternal: -+ default: -+ m_soundData->m_type = SoundObject::External; -+ break; -+ } -+ -+ m_soundData->m_soundObj = popplersound->copy(); -+} -+ -+SoundObject::~SoundObject() -+{ -+ delete m_soundData; -+} -+ -+SoundObject::SoundType SoundObject::soundType() const -+{ -+ return m_soundData->m_type; -+} -+ -+QString SoundObject::url() const -+{ -+ if ( m_soundData->m_type != SoundObject::External ) -+ return QString(); -+ -+ GooString * goo = m_soundData->m_soundObj->getFileName(); -+ return goo ? QString( goo->c_str() ) : QString(); -+} -+ -+QByteArray SoundObject::data() const -+{ -+ if ( m_soundData->m_type != SoundObject::Embedded ) -+ return QByteArray(); -+ -+ Stream *stream = m_soundData->m_soundObj->getStream(); -+ stream->reset(); -+ int dataLen = 0; -+ QByteArray fileArray; -+ int i; -+ while ( (i = stream->getChar()) != EOF) { -+ fileArray[dataLen] = (char)i; -+ ++dataLen; -+ } -+ fileArray.resize(dataLen); -+ -+ return fileArray; -+} -+ -+double SoundObject::samplingRate() const -+{ -+ return m_soundData->m_soundObj->getSamplingRate(); -+} -+ -+int SoundObject::channels() const -+{ -+ return m_soundData->m_soundObj->getChannels(); -+} -+ -+int SoundObject::bitsPerSample() const -+{ -+ return m_soundData->m_soundObj->getBitsPerSample(); -+} -+ -+SoundObject::SoundEncoding SoundObject::soundEncoding() const -+{ -+ switch ( m_soundData->m_soundObj->getEncoding() ) -+ { -+ case soundRaw: -+ return SoundObject::Raw; -+ case soundSigned: -+ return SoundObject::Signed; -+ case soundMuLaw: -+ return SoundObject::muLaw; -+ case soundALaw: -+ return SoundObject::ALaw; -+ } -+ return SoundObject::Raw; -+} -+ -+} -diff --git a/qt4/src/poppler-textbox.cc b/qt4/src/poppler-textbox.cc -new file mode 100644 -index 00000000..88cf2a9e ---- /dev/null -+++ b/qt4/src/poppler-textbox.cc -@@ -0,0 +1,63 @@ -+/* poppler-qt.h: qt interface to poppler -+ * Copyright (C) 2005, Brad Hards -+ * Copyright (C) 2006-2008, Albert Astals Cid -+ * Copyright (C) 2008, Pino Toscano -+ * -+ * 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-qt4.h" -+#include "poppler-private.h" -+ -+namespace Poppler { -+ -+TextBox::TextBox(const QString& text, const QRectF &bBox) -+{ -+ m_data = new TextBoxData(); -+ m_data->text = text; -+ m_data->bBox = bBox; -+} -+ -+TextBox::~TextBox() -+{ -+ delete m_data; -+} -+ -+QString TextBox::text() const -+{ -+ return m_data->text; -+} -+ -+QRectF TextBox::boundingBox() const -+{ -+ return m_data->bBox; -+} -+ -+TextBox *TextBox::nextWord() const -+{ -+ return m_data->nextWord; -+} -+ -+QRectF TextBox::charBoundingBox(int i) const -+{ -+ return m_data->charBBoxes.value(i); -+} -+ -+bool TextBox::hasSpaceAfter() const -+{ -+ return m_data->hasSpaceAfter; -+} -+ -+} -diff --git a/qt4/tests/.gitignore b/qt4/tests/.gitignore -new file mode 100644 -index 00000000..3746eb87 ---- /dev/null -+++ b/qt4/tests/.gitignore -@@ -0,0 +1,33 @@ -+.deps -+.libs -+*.la -+*.lo -+*.moc -+Makefile -+Makefile.in -+stress-poppler-qt4 -+stress-poppler-dir -+test-poppler-qt4 -+test-password-qt4 -+poppler-attachments -+poppler-fonts -+poppler-texts -+poppler-forms -+stress-threads-qt4 -+test-render-to-file -+check_actualtext -+check_attachments -+check_dateConversion -+check_fonts -+check_goostring -+check_lexer -+check_links -+check_metadata -+check_optcontent -+check_permissions -+check_pagelayout -+check_pagemode -+check_password -+check_search -+check_strings -+ -diff --git a/qt4/tests/CMakeLists.txt b/qt4/tests/CMakeLists.txt -new file mode 100644 -index 00000000..a01a638a ---- /dev/null -+++ b/qt4/tests/CMakeLists.txt -@@ -0,0 +1,67 @@ -+add_definitions(${QT4_DEFINITIONS}) -+add_definitions(-DTESTDATADIR=\"${TESTDATADIR}\") -+ -+include_directories( -+ ${CMAKE_CURRENT_SOURCE_DIR} -+ ${CMAKE_CURRENT_SOURCE_DIR}/../src -+ ${CMAKE_CURRENT_BINARY_DIR} -+ ${QT4_INCLUDE_DIR} -+) -+ -+macro(QT4_ADD_SIMPLETEST exe source) -+ string(REPLACE "-" "" test_name ${exe}) -+ set(${test_name}_SOURCES -+ ${source} -+ ) -+ poppler_add_test(${exe} BUILD_QT4_TESTS ${${test_name}_SOURCES}) -+ target_link_libraries(${exe} poppler-qt4) -+ if(MSVC) -+ target_link_libraries(${exe} poppler ${poppler_LIBS}) -+ endif() -+endmacro(QT4_ADD_SIMPLETEST) -+ -+macro(QT4_ADD_QTEST exe source) -+ if (QT4_QTTEST_FOUND) -+ string(REPLACE "-" "" test_name ${exe}) -+ set(${test_name}_SOURCES -+ ${source} -+ ) -+ poppler_add_unittest(${exe} BUILD_QT4_TESTS ${${test_name}_SOURCES}) -+ qt4_automoc(${${test_name}_SOURCES}) -+ target_link_libraries(${exe} poppler-qt4 ${QT4_QTTEST_LIBRARY}) -+ if(MSVC) -+ target_link_libraries(${exe} poppler ${poppler_LIBS}) -+ endif() -+ endif () -+endmacro(QT4_ADD_QTEST) -+ -+ -+qt4_add_simpletest(test-poppler-qt4 test-poppler-qt4.cpp) -+qt4_add_simpletest(test-password-qt4 test-password-qt4.cpp) -+qt4_add_simpletest(test-render-to-file-qt4 test-render-to-file.cpp) -+qt4_add_simpletest(poppler-qt4-forms poppler-forms.cpp) -+qt4_add_simpletest(poppler-qt4-fonts poppler-fonts.cpp) -+qt4_add_simpletest(poppler-qt4-attachments poppler-attachments.cpp) -+qt4_add_simpletest(stress-poppler-qt4 stress-poppler-qt4.cpp) -+qt4_add_simpletest(stress-poppler-dir-qt4 stress-poppler-dir.cpp) -+qt4_add_simpletest(stress-threads-qt4 stress-threads-qt4.cpp) -+qt4_add_simpletest(poppler-qt4-texts poppler-texts.cpp) -+ -+qt4_add_qtest(check_qt4_attachments check_attachments.cpp) -+qt4_add_qtest(check_qt4_dateConversion check_dateConversion.cpp) -+qt4_add_qtest(check_qt4_fonts check_fonts.cpp) -+qt4_add_qtest(check_qt4_links check_links.cpp) -+qt4_add_qtest(check_qt4_metadata check_metadata.cpp) -+qt4_add_qtest(check_qt4_optcontent check_optcontent.cpp) -+qt4_add_qtest(check_qt4_pagelayout check_pagelayout.cpp) -+qt4_add_qtest(check_qt4_pagemode check_pagemode.cpp) -+qt4_add_qtest(check_qt4_password check_password.cpp) -+qt4_add_qtest(check_qt4_permissions check_permissions.cpp) -+qt4_add_qtest(check_qt4_search check_search.cpp) -+qt4_add_qtest(check_qt4_actualtext check_actualtext.cpp) -+qt4_add_qtest(check_qt4_lexer check_lexer.cpp) -+qt4_add_qtest(check_qt4_pagelabelinfo check_pagelabelinfo.cpp) -+qt4_add_qtest(check_qt4_goostring check_goostring.cpp) -+if (NOT WIN32) -+ qt4_add_qtest(check_qt4_strings check_strings.cpp) -+endif () -diff --git a/qt4/tests/README.unittest b/qt4/tests/README.unittest -new file mode 100644 -index 00000000..02296e08 ---- /dev/null -+++ b/qt4/tests/README.unittest -@@ -0,0 +1,23 @@ -+The unittests for the Qt4 bindings rely on the QtTestLib package, and -+will not be built until this is installed. If you do not have it, then -+you can download it from the Trolltech website. -+ -+Note that there are a range of ways in which you can run the tests: -+1. "make check" will run all the tests. -+2. You can run a single test by executing the applicable -+executable. For example, you can run the PageMode tests by -+"./check_pagemode" -+3. You can run a single function within a single test by appending the -+name of the function to the executable. For example, if you just want -+to run the FullScreen test within the PageMode tests, you can -+"./check_pagemode checkFullScreen". Run the executable with -functions -+to get a list of all the functions. -+4. You can run a single function with specific data by appending the -+name of the function, followed by a colon, then the data label to the -+executable. For example, to just do the Author check within the -+metadata checks, you can "./check_metadata checkStrings:Author". -+ -+For a full list of options, run a executable with "-help". -+ -+Brad Hards -+bradh@frogmouth.net -diff --git a/qt4/tests/check_actualtext.cpp b/qt4/tests/check_actualtext.cpp -new file mode 100644 -index 00000000..5c765c51 ---- /dev/null -+++ b/qt4/tests/check_actualtext.cpp -@@ -0,0 +1,33 @@ -+#include -+ -+#include -+ -+#include -+ -+class TestActualText: public QObject -+{ -+ Q_OBJECT -+private slots: -+ void checkActualText1(); -+}; -+ -+void TestActualText::checkActualText1() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/WithActualText.pdf"); -+ QVERIFY( doc ); -+ -+ Poppler::Page *page = doc->page(0); -+ QVERIFY( page ); -+ -+ QCOMPARE( page->text(QRectF()), QString("The slow brown fox jumps over the black dog.") ); -+ -+ delete page; -+ -+ delete doc; -+} -+ -+QTEST_MAIN(TestActualText) -+ -+#include "check_actualtext.moc" -+ -diff --git a/qt4/tests/check_attachments.cpp b/qt4/tests/check_attachments.cpp -new file mode 100644 -index 00000000..73e31502 ---- /dev/null -+++ b/qt4/tests/check_attachments.cpp -@@ -0,0 +1,157 @@ -+#include -+ -+#include -+ -+#include -+ -+class TestAttachments: public QObject -+{ -+ Q_OBJECT -+private slots: -+ void checkNoAttachments(); -+ void checkAttach1(); -+ void checkAttach2(); -+ void checkAttach3(); -+ void checkAttach4(); -+}; -+ -+void TestAttachments::checkNoAttachments() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/truetype.pdf"); -+ QVERIFY( doc ); -+ -+ QCOMPARE( doc->hasEmbeddedFiles(), false ); -+ -+ delete doc; -+} -+ -+void TestAttachments::checkAttach1() -+{ -+ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/WithAttachments.pdf"); -+ QVERIFY( doc ); -+ -+ QVERIFY( doc->hasEmbeddedFiles() ); -+ -+ QList fileList = doc->embeddedFiles(); -+ QCOMPARE( fileList.size(), 2 ); -+ -+ Poppler::EmbeddedFile *embfile = fileList.at(0); -+ QCOMPARE( embfile->name(), QString( "kroller.png" ) ); -+ QCOMPARE( embfile->description(), QString() ); -+ QCOMPARE( embfile->createDate(), QDateTime( QDate(), QTime() ) ); -+ QCOMPARE( embfile->modDate(), QDateTime( QDate(), QTime() ) ); -+ QCOMPARE( embfile->mimeType(), QString() ); -+ -+ QFile file(TESTDATADIR "/unittestcases/kroller.png" ); -+ QVERIFY( file.open( QIODevice::ReadOnly ) ); -+ QByteArray krollerData = file.readAll(); -+ QByteArray embdata = embfile->data(); -+ QCOMPARE( krollerData, embdata ); -+ -+ -+ Poppler::EmbeddedFile *embfile2 = fileList.at(1); -+ QCOMPARE( embfile2->name(), QString("gnome-64.gif") ); -+ QCOMPARE( embfile2->description(), QString() ); -+ QCOMPARE( embfile2->modDate(), QDateTime( QDate(), QTime() ) ); -+ QCOMPARE( embfile2->createDate(), QDateTime( QDate(), QTime() ) ); -+ QCOMPARE( embfile2->mimeType(), QString() ); -+ -+ QFile file2(TESTDATADIR "/unittestcases/gnome-64.gif" ); -+ QVERIFY( file2.open( QIODevice::ReadOnly ) ); -+ QByteArray g64Data = file2.readAll(); -+ QByteArray emb2data = embfile2->data(); -+ QCOMPARE( g64Data, emb2data ); -+ -+ delete doc; -+} -+ -+ -+void TestAttachments::checkAttach2() -+{ -+ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/A6EmbeddedFiles.pdf"); -+ QVERIFY( doc ); -+ -+ QVERIFY( doc->hasEmbeddedFiles() ); -+ -+ QList fileList; -+ fileList = doc->embeddedFiles(); -+ QCOMPARE( fileList.size(), 3 ); -+ -+ Poppler::EmbeddedFile *embfile1 = fileList.at(0); -+ QCOMPARE( embfile1->name(), QString("Acro7 thoughts") ); -+ QCOMPARE( embfile1->description(), QString() ); -+ QCOMPARE( embfile1->createDate(), QDateTime( QDate( 2003, 8, 4 ), QTime( 13, 54, 54), Qt::UTC ) ); -+ QCOMPARE( embfile1->modDate(), QDateTime( QDate( 2003, 8, 4 ), QTime( 14, 15, 27), Qt::UTC ) ); -+ QCOMPARE( embfile1->mimeType(), QString("text/xml") ); -+ -+ Poppler::EmbeddedFile *embfile2 = fileList.at(1); -+ QCOMPARE( embfile2->name(), QString("acro transitions 1.xls") ); -+ QCOMPARE( embfile2->description(), QString() ); -+ QCOMPARE( embfile2->createDate(), QDateTime( QDate( 2003, 7, 18 ), QTime( 21, 7, 16), Qt::UTC ) ); -+ QCOMPARE( embfile2->modDate(), QDateTime( QDate( 2003, 7, 22 ), QTime( 13, 4, 40), Qt::UTC ) ); -+ QCOMPARE( embfile2->mimeType(), QString("application/excel") ); -+ -+ Poppler::EmbeddedFile *embfile3 = fileList.at(2); -+ QCOMPARE( embfile3->name(), QString("apago_pdfe_wide.gif") ); -+ QCOMPARE( embfile3->description(), QString() ); -+ QCOMPARE( embfile3->createDate(), QDateTime( QDate( 2003, 1, 31 ), QTime( 15, 54, 29), Qt::UTC ) ); -+ QCOMPARE( embfile3->modDate(), QDateTime( QDate( 2003, 1, 31 ), QTime( 15, 52, 58), Qt::UTC ) ); -+ QCOMPARE( embfile3->mimeType(), QString() ); -+ -+ delete doc; -+} -+ -+void TestAttachments::checkAttach3() -+{ -+ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/shapes+attachments.pdf"); -+ QVERIFY( doc ); -+ -+ QVERIFY( doc->hasEmbeddedFiles() ); -+ -+ QList fileList; -+ fileList = doc->embeddedFiles(); -+ QCOMPARE( fileList.size(), 1 ); -+ -+ Poppler::EmbeddedFile *embfile = fileList.at(0); -+ QCOMPARE( embfile->name(), QString( "ADEX1.xpdf.pgp" ) ); -+ QCOMPARE( embfile->description(), QString() ); -+ QCOMPARE( embfile->createDate(), QDateTime( QDate( 2004, 3, 29 ), QTime( 19, 37, 16), Qt::UTC ) ); -+ QCOMPARE( embfile->modDate(), QDateTime( QDate( 2004, 3, 29 ), QTime( 19, 37, 16), Qt::UTC ) ); -+ QCOMPARE( embfile->mimeType(), QString() ); -+ delete doc; -+ -+} -+ -+void TestAttachments::checkAttach4() -+{ -+ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/imageretrieve+attachment.pdf"); -+ QVERIFY( doc ); -+ -+ QVERIFY( doc->hasEmbeddedFiles() ); -+ -+ QList fileList; -+ fileList = doc->embeddedFiles(); -+ QCOMPARE( fileList.size(), 1 ); -+ -+ Poppler::EmbeddedFile *embfile = fileList.at(0); -+ QCOMPARE( embfile->name(), QString( "export-altona.csv" ) ); -+ QCOMPARE( embfile->description(), QString("Altona Export") ); -+ QCOMPARE( embfile->createDate(), QDateTime( QDate( 2005, 8, 30 ), QTime( 20, 49, 35), Qt::UTC ) ); -+ QCOMPARE( embfile->modDate(), QDateTime( QDate( 2005, 8, 30 ), QTime( 20, 49, 52), Qt::UTC ) ); -+ QCOMPARE( embfile->mimeType(), QString("application/vnd.ms-excel") ); -+ delete doc; -+ -+} -+ -+QTEST_MAIN(TestAttachments) -+#include "check_attachments.moc" -+ -diff --git a/qt4/tests/check_dateConversion.cpp b/qt4/tests/check_dateConversion.cpp -new file mode 100644 -index 00000000..c1f84e2f ---- /dev/null -+++ b/qt4/tests/check_dateConversion.cpp -@@ -0,0 +1,142 @@ -+#include -+ -+Q_DECLARE_METATYPE(QDate) -+Q_DECLARE_METATYPE(QTime) -+ -+#include -+ -+class TestDateConv: public QObject -+{ -+ Q_OBJECT -+private slots: -+ void initTestCase(); -+ void checkDates_data(); -+ void checkDates(); -+ void checkInvalidDates_data(); -+ void checkInvalidDates(); -+}; -+ -+void TestDateConv::initTestCase() -+{ -+ qRegisterMetaType("QDate"); -+ qRegisterMetaType("QTime"); -+} -+ -+void TestDateConv::checkDates_data() -+{ -+ QTest::addColumn("input"); -+ QTest::addColumn("day"); -+ QTest::addColumn("time"); -+ -+ // This is a typical case - all data provided -+ QTest::newRow("D:20040101121110") -+ << QByteArray("D:20040101121110Z") -+ << QDate( 2004, 1, 1) -+ << QTime( 12, 11, 10); -+ -+ // The D: is strongly recommended, but optional -+ QTest::newRow("20040101121110") -+ << QByteArray("20040101121110Z") -+ << QDate( 2004, 1, 1) -+ << QTime( 12, 11, 10); -+ -+ // Only the year is actually required -+ QTest::newRow("D:2006") -+ << QByteArray("D:2006") -+ << QDate( 2006, 1, 1) -+ << QTime( 0, 0, 0); -+ -+ QTest::newRow("D:200602") -+ << QByteArray("D:200602") -+ << QDate( 2006, 2, 1) -+ << QTime( 0, 0, 0); -+ -+ QTest::newRow("D:20060304") -+ << QByteArray("D:20060304") -+ << QDate( 2006, 3, 4) -+ << QTime( 0, 0, 0); -+ -+ QTest::newRow("D:2006030405") -+ << QByteArray("D:2006030405") -+ << QDate( 2006, 3, 4) -+ << QTime( 5, 0, 0); -+ -+ QTest::newRow("D:200603040512") -+ << QByteArray("D:200603040512") -+ << QDate( 2006, 3, 4) -+ << QTime( 5, 12, 0); -+ -+ // If the timezone isn't specified, I assume UTC -+ QTest::newRow("D:20060304051226") -+ << QByteArray("D:20060304051226") -+ << QDate( 2006, 3, 4) -+ << QTime( 5, 12, 26); -+ -+ // Check for real timezone conversions -+ QTest::newRow("D:20030131115258-04'00'") -+ << QByteArray("D:20030131115258-04'00'") -+ << QDate( 2003, 1, 31) -+ << QTime( 15, 52, 58); -+ -+ QTest::newRow("D:20030131115258+05'00'") -+ << QByteArray("D:20030131115258+05'00'") -+ << QDate( 2003, 1, 31) -+ << QTime( 6, 52, 58); -+ -+ // There are places that have non-hour offsets -+ // Yep, that means you Adelaide. -+ QTest::newRow("D:20030131115258+08'30'") -+ << QByteArray("D:20030131115258+08'30'") -+ << QDate( 2003, 1, 31) -+ << QTime( 3, 22, 58); -+ -+ QTest::newRow("D:20030131115258-08'30'") -+ << QByteArray("D:20030131115258-08'30'") -+ << QDate( 2003, 1, 31) -+ << QTime( 20, 22, 58); -+} -+ -+void TestDateConv::checkDates() -+{ -+ QFETCH(QByteArray, input); -+ QFETCH(QDate, day); -+ QFETCH(QTime, time); -+ -+ QCOMPARE( Poppler::convertDate(input.data()), QDateTime(day, time, Qt::UTC) ); -+} -+ -+void TestDateConv::checkInvalidDates_data() -+{ -+ QTest::addColumn("input"); -+ -+ // Null data -+ QTest::newRow("Null data") -+ << QByteArray(); -+ -+ // Empty data -+ QTest::newRow("Empty data") -+ << QByteArray(""); -+ -+ // Empty data -+ QTest::newRow("One character") -+ << QByteArray("D"); -+ -+ // Empty data -+ QTest::newRow("'D:'") -+ << QByteArray("D:"); -+ -+ // Empty data -+ QTest::newRow("Not a date") -+ << QByteArray("D:IAmNotAValidDate"); -+} -+ -+void TestDateConv::checkInvalidDates() -+{ -+ QFETCH(QByteArray, input); -+ -+ QCOMPARE(Poppler::convertDate(input.data()), QDateTime()); -+} -+ -+QTEST_MAIN(TestDateConv) -+ -+#include "check_dateConversion.moc" -diff --git a/qt4/tests/check_fonts.cpp b/qt4/tests/check_fonts.cpp -new file mode 100644 -index 00000000..77579a97 ---- /dev/null -+++ b/qt4/tests/check_fonts.cpp -@@ -0,0 +1,248 @@ -+#include -+ -+#include -+ -+#include -+ -+class TestFontsData: public QObject -+{ -+ Q_OBJECT -+private slots: -+ void checkNoFonts(); -+ void checkType1(); -+ void checkType3(); -+ void checkTrueType(); -+ void checkFontIterator(); -+ void checkSecondDocumentQuery(); -+ void checkMultipleIterations(); -+ void checkScanForFonts(); -+}; -+ -+ -+static QList loadFontsViaIterator( Poppler::Document *doc, int from = 0, int count = -1 ) -+{ -+ int num = count == -1 ? doc->numPages() - from : count; -+ QList list; -+ std::unique_ptr< Poppler::FontIterator > it( doc->newFontIterator( from ) ); -+ while ( it->hasNext() && num ) -+ { -+ list += it->next(); -+ --num; -+ } -+ return list; -+} -+ -+namespace Poppler -+{ -+static bool operator==( const FontInfo &f1, const FontInfo &f2 ) -+{ -+ if ( f1.name() != f2.name() ) -+ return false; -+ if ( f1.file() != f2.file() ) -+ return false; -+ if ( f1.isEmbedded() != f2.isEmbedded() ) -+ return false; -+ if ( f1.isSubset() != f2.isSubset() ) -+ return false; -+ if ( f1.type() != f2.type() ) -+ return false; -+ if ( f1.typeName() != f2.typeName() ) -+ return false; -+ return true; -+} -+} -+ -+void TestFontsData::checkNoFonts() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/tests/image.pdf"); -+ QVERIFY( doc ); -+ -+ QList listOfFonts = doc->fonts(); -+ QCOMPARE( listOfFonts.size(), 0 ); -+ -+ delete doc; -+} -+ -+void TestFontsData::checkType1() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/tests/text.pdf"); -+ QVERIFY( doc ); -+ -+ QList listOfFonts = doc->fonts(); -+ QCOMPARE( listOfFonts.size(), 1 ); -+ QCOMPARE( listOfFonts.at(0).name(), QString("Helvetica") ); -+ QCOMPARE( listOfFonts.at(0).type(), Poppler::FontInfo::Type1 ); -+ QCOMPARE( listOfFonts.at(0).typeName(), QString("Type 1") ); -+ -+ QCOMPARE( listOfFonts.at(0).isEmbedded(), false ); -+ QCOMPARE( listOfFonts.at(0).isSubset(), false ); -+ -+ delete doc; -+} -+ -+void TestFontsData::checkType3() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/tests/type3.pdf"); -+ QVERIFY( doc ); -+ -+ QList listOfFonts = doc->fonts(); -+ QCOMPARE( listOfFonts.size(), 2 ); -+ QCOMPARE( listOfFonts.at(0).name(), QString("Helvetica") ); -+ QCOMPARE( listOfFonts.at(0).type(), Poppler::FontInfo::Type1 ); -+ QCOMPARE( listOfFonts.at(0).typeName(), QString("Type 1") ); -+ -+ QCOMPARE( listOfFonts.at(0).isEmbedded(), false ); -+ QCOMPARE( listOfFonts.at(0).isSubset(), false ); -+ -+ QCOMPARE( listOfFonts.at(1).name(), QString("") ); -+ QCOMPARE( listOfFonts.at(1).type(), Poppler::FontInfo::Type3 ); -+ QCOMPARE( listOfFonts.at(1).typeName(), QString("Type 3") ); -+ -+ QCOMPARE( listOfFonts.at(1).isEmbedded(), true ); -+ QCOMPARE( listOfFonts.at(1).isSubset(), false ); -+ -+ delete doc; -+} -+ -+void TestFontsData::checkTrueType() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/truetype.pdf"); -+ QVERIFY( doc ); -+ -+ QList listOfFonts = doc->fonts(); -+ QCOMPARE( listOfFonts.size(), 2 ); -+ QCOMPARE( listOfFonts.at(0).name(), QString("Arial-BoldMT") ); -+ QCOMPARE( listOfFonts.at(0).type(), Poppler::FontInfo::TrueType ); -+ QCOMPARE( listOfFonts.at(0).typeName(), QString("TrueType") ); -+ -+ QCOMPARE( listOfFonts.at(0).isEmbedded(), false ); -+ QCOMPARE( listOfFonts.at(0).isSubset(), false ); -+ -+ QCOMPARE( listOfFonts.at(1).name(), QString("ArialMT") ); -+ QCOMPARE( listOfFonts.at(1).type(), Poppler::FontInfo::TrueType ); -+ QCOMPARE( listOfFonts.at(1).typeName(), QString("TrueType") ); -+ -+ QCOMPARE( listOfFonts.at(1).isEmbedded(), false ); -+ QCOMPARE( listOfFonts.at(1).isSubset(), false ); -+ -+ delete doc; -+} -+ -+void TestFontsData::checkFontIterator() -+{ -+ // loading a 1-page document -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/tests/type3.pdf"); -+ QVERIFY( doc ); -+ // loading a 6-pages document -+ Poppler::Document *doc6 = Poppler::Document::load(TESTDATADIR "/tests/cropbox.pdf"); -+ QVERIFY( doc6 ); -+ -+ std::unique_ptr< Poppler::FontIterator > it; -+ -+ // some tests with the 1-page document: -+ // - check a default iterator -+ it.reset( doc->newFontIterator() ); -+ QVERIFY( it->hasNext() ); -+ // - check an iterator for negative pages to behave as 0 -+ it.reset( doc->newFontIterator( -1 ) ); -+ QVERIFY( it->hasNext() ); -+ // - check an iterator for pages out of the page limit -+ it.reset( doc->newFontIterator( 1 ) ); -+ QVERIFY( !it->hasNext() ); -+ // - check that it reaches the end after 1 iteration -+ it.reset( doc->newFontIterator() ); -+ QVERIFY( it->hasNext() ); -+ it->next(); -+ QVERIFY( !it->hasNext() ); -+ -+ // some tests with the 6-page document: -+ // - check a default iterator -+ it.reset( doc6->newFontIterator() ); -+ QVERIFY( it->hasNext() ); -+ // - check an iterator for pages out of the page limit -+ it.reset( doc6->newFontIterator( 6 ) ); -+ QVERIFY( !it->hasNext() ); -+ // - check that it reaches the end after 6 iterations -+ it.reset( doc6->newFontIterator() ); -+ QVERIFY( it->hasNext() ); -+ it->next(); -+ QVERIFY( it->hasNext() ); -+ it->next(); -+ QVERIFY( it->hasNext() ); -+ it->next(); -+ QVERIFY( it->hasNext() ); -+ it->next(); -+ QVERIFY( it->hasNext() ); -+ it->next(); -+ QVERIFY( it->hasNext() ); -+ it->next(); -+ QVERIFY( !it->hasNext() ); -+ -+ delete doc; -+ delete doc6; -+} -+ -+void TestFontsData::checkSecondDocumentQuery() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/tests/type3.pdf"); -+ QVERIFY( doc ); -+ -+ QList listOfFonts = doc->fonts(); -+ QCOMPARE( listOfFonts.size(), 2 ); -+ // check we get the very same result when calling fonts() again (#19405) -+ QList listOfFonts2 = doc->fonts(); -+ QCOMPARE( listOfFonts, listOfFonts2 ); -+ -+ delete doc; -+} -+ -+void TestFontsData::checkMultipleIterations() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/tests/type3.pdf"); -+ QVERIFY( doc ); -+ -+ QList listOfFonts = loadFontsViaIterator( doc ); -+ QCOMPARE( listOfFonts.size(), 2 ); -+ QList listOfFonts2 = loadFontsViaIterator( doc ); -+ QCOMPARE( listOfFonts, listOfFonts2 ); -+ -+ delete doc; -+} -+ -+void TestFontsData::checkScanForFonts() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/tests/fonts.pdf"); -+ QVERIFY( doc ); -+ -+ QList listOfFonts = doc->fonts(); -+ QCOMPARE( listOfFonts.size(), 3 ); -+ // check we get the very same result when gatering fonts using scanForFonts -+ QList listOfFonts2; -+ for ( int i = 0; i < doc->numPages(); ++i ) -+ { -+ doc->scanForFonts( 1, &listOfFonts2 ); -+ } -+ QCOMPARE( listOfFonts, listOfFonts2 ); -+ -+ // check doing a second scanForFonts gives no result -+ QList listOfFonts3; -+ for ( int i = 0; i < doc->numPages(); ++i ) -+ { -+ doc->scanForFonts( 1, &listOfFonts3 ); -+ } -+ QVERIFY( listOfFonts3.isEmpty() ); -+ -+ delete doc; -+} -+ -+QTEST_MAIN(TestFontsData) -+#include "check_fonts.moc" -+ -diff --git a/qt4/tests/check_goostring.cpp b/qt4/tests/check_goostring.cpp -new file mode 100644 -index 00000000..69f7cdc5 ---- /dev/null -+++ b/qt4/tests/check_goostring.cpp -@@ -0,0 +1,127 @@ -+#include -+#include -+ -+#include "goo/GooString.h" -+ -+class TestGooString : public QObject -+{ -+ Q_OBJECT -+private slots: -+ void testInsertData_data(); -+ void testInsertData(); -+ void testInsert(); -+ void testFormat(); -+}; -+ -+void TestGooString::testInsertData_data() -+{ -+ QTest::addColumn("string"); -+ QTest::addColumn("addition"); -+ QTest::addColumn("position"); -+ QTest::addColumn("result"); -+ -+ QTest::newRow("foo") << QByteArray("foo") << QByteArray("bar") << 0 << QByteArray("barfoo"); -+ QTest::newRow("") << QByteArray() << QByteArray("bar") << 0 << QByteArray("bar"); -+ QTest::newRow("foo+bar #1") << QByteArray("f+bar") << QByteArray("oo") << 1 << QByteArray("foo+bar"); -+ QTest::newRow("foo+bar #2") << QByteArray("fobar") << QByteArray("o+") << 2 << QByteArray("foo+bar"); -+ QTest::newRow("foo+bar #last") << QByteArray("foo+r") << QByteArray("ba") << 4 << QByteArray("foo+bar"); -+ QTest::newRow("foo+bar #end") << QByteArray("foo+") << QByteArray("bar") << 4 << QByteArray("foo+bar"); -+ QTest::newRow("long #start") << QByteArray("very string") << QByteArray("long long long long long ") << 5 << QByteArray("very long long long long long string"); -+} -+ -+void TestGooString::testInsertData() -+{ -+ QFETCH(QByteArray, string); -+ QFETCH(QByteArray, addition); -+ QFETCH(int, position); -+ QFETCH(QByteArray, result); -+ -+ GooString goo(string.constData()); -+ QCOMPARE(goo.c_str(), string.constData()); -+ goo.insert(position, addition.constData()); -+ QCOMPARE(goo.c_str(), result.constData()); -+} -+ -+void TestGooString::testInsert() -+{ -+ { -+ GooString goo; -+ goo.insert(0, "."); -+ goo.insert(0, "This is a very long long test string"); -+ QCOMPARE(goo.c_str(), "This is a very long long test string."); -+ } -+ { -+ GooString goo; -+ goo.insert(0, "second-part-third-part"); -+ goo.insert(0, "first-part-"); -+ QCOMPARE(goo.c_str(), "first-part-second-part-third-part"); -+ } -+} -+ -+void TestGooString::testFormat() -+{ -+ { -+ const QScopedPointer goo(GooString::format("{0:d},{1:x}", 1, 0xF)); -+ QCOMPARE(goo->c_str(), "1,f"); -+ } -+ { -+ const QScopedPointer goo(GooString::format("{0:d},{0:x},{0:X},{0:o},{0:b},{0:w}", 0xA)); -+ QCOMPARE(goo->c_str(), "10,a,A,12,1010, "); -+ } -+ { -+ const QScopedPointer goo(GooString::format("{0:d},{0:x},{0:X},{0:o},{0:b}", -0xA)); -+ QCOMPARE(goo->c_str(), "-10,-a,-A,-12,-1010"); -+ } -+ { -+ const QScopedPointer goo(GooString::format("{0:c}{1:c}{2:c}{3:c}", -+ 'T', (char)'E', (short)'S', (int)'T')); -+ QCOMPARE(goo->c_str(), "TEST"); -+ -+ const QScopedPointer goo2(GooString::format("{0:s} {1:t}", "TEST", goo.data())); -+ QCOMPARE(goo2->c_str(), "TEST TEST"); -+ } -+ { -+ const QScopedPointer goo(GooString::format("{0:ud} {1:d} {2:d}", -+ UINT_MAX, INT_MAX, INT_MIN)); -+ const QByteArray expected = QString("%1 %2 %3").arg(UINT_MAX).arg(INT_MAX).arg(INT_MIN).toLatin1(); -+ QCOMPARE(goo->c_str(), expected.constData()); -+ } -+ { -+ const QScopedPointer goo(GooString::format("{0:uld} {1:ld} {2:ld}", -+ ULONG_MAX, LONG_MAX, LONG_MIN)); -+ const QByteArray expected = QString("%1 %2 %3").arg(ULONG_MAX).arg(LONG_MAX).arg(LONG_MIN).toLatin1(); -+ QCOMPARE(goo->c_str(), expected.constData()); -+ } -+ { -+ const QScopedPointer goo(GooString::format("{0:ulld} {1:lld} {2:lld}", -+ ULLONG_MAX, LLONG_MAX, LLONG_MIN)); -+ const QByteArray expected = QString("%1 %2 %3").arg(ULLONG_MAX).arg(LLONG_MAX).arg(LLONG_MIN).toLatin1(); -+ QCOMPARE(goo->c_str(), expected.constData()); -+ } -+ { -+ const QScopedPointer gooD(GooString::format("{0:.1f} {0:.1g} {0:.1gs} | {1:.1f} {1:.1g} {1:.1gs}", 1., .012)); -+ const QScopedPointer gooF(GooString::format("{0:.1f} {0:.1g} {0:.1gs} | {1:.1f} {1:.1g} {1:.1gs}", 1.f, .012f)); -+ QCOMPARE(gooD->c_str(), "1.0 1 1 | 0.0 0 0.01"); -+ QCOMPARE(gooF->c_str(), "1.0 1 1 | 0.0 0 0.01"); -+ } -+ { -+ const QScopedPointer goo(GooString::format("{0:.4f} {0:.4g} {0:.4gs}", .012)); -+ QCOMPARE(goo->c_str(), "0.0120 0.012 0.012"); -+ } -+ { -+ const QScopedPointer goo(GooString::format("{{ SomeText {0:d} }}", 1)); -+ QCOMPARE(goo->c_str(), "{ SomeText 1 }"); -+ } -+ { -+ const QScopedPointer goo(GooString::format("{{{{ {{ SomeText {0:d}", 2)); -+ QCOMPARE(goo->c_str(), "{{ { SomeText 2"); -+ } -+ { -+ const QScopedPointer goo(GooString::format("SomeText {0:d} }} }}}}", 3)); -+ QCOMPARE(goo->c_str(), "SomeText 3 } }}"); -+ } -+} -+ -+QTEST_MAIN(TestGooString) -+#include "check_goostring.moc" -+ -diff --git a/qt4/tests/check_lexer.cpp b/qt4/tests/check_lexer.cpp -new file mode 100644 -index 00000000..93c3621d ---- /dev/null -+++ b/qt4/tests/check_lexer.cpp -@@ -0,0 +1,107 @@ -+#include -+ -+#include "Object.h" -+#include "Lexer.h" -+ -+class TestLexer : public QObject -+{ -+ Q_OBJECT -+private slots: -+ void testNumbers(); -+}; -+ -+void TestLexer::testNumbers() -+{ -+ char data[] = "0 1 -1 2147483647 -2147483647 2147483648 -2147483648 4294967297 -2147483649 0.1 1.1 -1.1 2147483647.1 -2147483647.1 2147483648.1 -2147483648.1 4294967297.1 -2147483649.1 9223372036854775807 18446744073709551615"; -+ MemStream *stream = new MemStream(data, 0, strlen(data), Object(objNull)); -+ Lexer *lexer = new Lexer(NULL, stream); -+ QVERIFY( lexer ); -+ -+ Object obj; -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objInt); -+ QCOMPARE(obj.getInt(), 0); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objInt); -+ QCOMPARE(obj.getInt(), 1); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objInt); -+ QCOMPARE(obj.getInt(), -1); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objInt); -+ QCOMPARE(obj.getInt(), 2147483647); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objInt); -+ QCOMPARE(obj.getInt(), -2147483647); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objInt64); -+ QCOMPARE(obj.getInt64(), 2147483648ll); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objInt); -+ QCOMPARE(obj.getInt(), -2147483647-1); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objInt64); -+ QCOMPARE(obj.getInt64(), 4294967297ll); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objInt64); -+ QCOMPARE(obj.getInt64(), -2147483649ll); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objReal); -+ QCOMPARE(obj.getReal(), 0.1); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objReal); -+ QCOMPARE(obj.getReal(), 1.1); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objReal); -+ QCOMPARE(obj.getReal(), -1.1); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objReal); -+ QCOMPARE(obj.getReal(), 2147483647.1); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objReal); -+ QCOMPARE(obj.getReal(), -2147483647.1); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objReal); -+ QCOMPARE(obj.getReal(), 2147483648.1); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objReal); -+ QCOMPARE(obj.getReal(), -2147483648.1); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objReal); -+ QCOMPARE(obj.getReal(), 4294967297.1); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objReal); -+ QCOMPARE(obj.getReal(), -2147483649.1); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objInt64); -+ QCOMPARE(obj.getInt64(), 9223372036854775807ll); -+ -+ obj = lexer->getObj(); -+ QCOMPARE(obj.getType(), objReal); -+ QCOMPARE(obj.getReal(), 18446744073709551616.); -+ -+ delete lexer; -+} -+ -+QTEST_MAIN(TestLexer) -+#include "check_lexer.moc" -+ -diff --git a/qt4/tests/check_links.cpp b/qt4/tests/check_links.cpp -new file mode 100644 -index 00000000..e5c17368 ---- /dev/null -+++ b/qt4/tests/check_links.cpp -@@ -0,0 +1,98 @@ -+#include -+ -+#include -+ -+#include -+ -+class TestLinks : public QObject -+{ -+ Q_OBJECT -+private slots: -+ void checkDocumentWithNoDests(); -+ void checkDests_xr01(); -+ void checkDests_xr02(); -+}; -+ -+static bool isDestinationValid_pageNumber( const Poppler::LinkDestination *dest, const Poppler::Document *doc ) -+{ -+ return dest->pageNumber() > 0 && dest->pageNumber() <= doc->numPages(); -+} -+ -+static bool isDestinationValid_name( const Poppler::LinkDestination *dest ) -+{ -+ return !dest->destinationName().isEmpty(); -+} -+ -+ -+void TestLinks::checkDocumentWithNoDests() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/WithAttachments.pdf"); -+ QVERIFY( doc ); -+ -+ std::unique_ptr< Poppler::LinkDestination > dest; -+ dest.reset( doc->linkDestination("no.dests.in.this.document") ); -+ QVERIFY( !isDestinationValid_pageNumber( dest.get(), doc ) ); -+ QVERIFY( isDestinationValid_name( dest.get() ) ); -+ -+ delete doc; -+} -+ -+void TestLinks::checkDests_xr01() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/xr01.pdf"); -+ QVERIFY( doc ); -+ -+ Poppler::Page *page = doc->page(0); -+ QVERIFY( page ); -+ -+ QList< Poppler::Link* > links = page->links(); -+ QCOMPARE( links.count(), 2 ); -+ -+ { -+ QCOMPARE( links.at(0)->linkType(), Poppler::Link::Goto ); -+ Poppler::LinkGoto *link = static_cast< Poppler::LinkGoto * >( links.at(0) ); -+ const Poppler::LinkDestination dest = link->destination(); -+ QVERIFY( !isDestinationValid_pageNumber( &dest, doc ) ); -+ QVERIFY( isDestinationValid_name( &dest ) ); -+ QCOMPARE( dest.destinationName(), QString::fromLatin1("section.1") ); -+ } -+ -+ { -+ QCOMPARE( links.at(1)->linkType(), Poppler::Link::Goto ); -+ Poppler::LinkGoto *link = static_cast< Poppler::LinkGoto * >( links.at(1) ); -+ const Poppler::LinkDestination dest = link->destination(); -+ QVERIFY( !isDestinationValid_pageNumber( &dest, doc ) ); -+ QVERIFY( isDestinationValid_name( &dest ) ); -+ QCOMPARE( dest.destinationName(), QString::fromLatin1("section.2") ); -+ } -+ -+ qDeleteAll(links); -+ delete page; -+ delete doc; -+} -+ -+void TestLinks::checkDests_xr02() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/xr02.pdf"); -+ QVERIFY( doc ); -+ -+ std::unique_ptr< Poppler::LinkDestination > dest; -+ dest.reset( doc->linkDestination("section.1") ); -+ QVERIFY( isDestinationValid_pageNumber( dest.get(), doc ) ); -+ QVERIFY( !isDestinationValid_name( dest.get() ) ); -+ dest.reset( doc->linkDestination("section.2") ); -+ QVERIFY( isDestinationValid_pageNumber( dest.get(), doc ) ); -+ QVERIFY( !isDestinationValid_name( dest.get() ) ); -+ dest.reset( doc->linkDestination("section.3") ); -+ QVERIFY( !isDestinationValid_pageNumber( dest.get(), doc ) ); -+ QVERIFY( isDestinationValid_name( dest.get() ) ); -+ -+ delete doc; -+} -+ -+QTEST_MAIN(TestLinks) -+ -+#include "check_links.moc" -diff --git a/qt4/tests/check_metadata.cpp b/qt4/tests/check_metadata.cpp -new file mode 100644 -index 00000000..fb4f7163 ---- /dev/null -+++ b/qt4/tests/check_metadata.cpp -@@ -0,0 +1,275 @@ -+#include -+ -+#include -+ -+class TestMetaData: public QObject -+{ -+ Q_OBJECT -+private slots: -+ void checkStrings_data(); -+ void checkStrings(); -+ void checkStrings2_data(); -+ void checkStrings2(); -+ void checkStringKeys(); -+ void checkLinearised(); -+ void checkNumPages(); -+ void checkDate(); -+ void checkPageSize(); -+ void checkPortraitOrientation(); -+ void checkLandscapeOrientation(); -+ void checkUpsideDownOrientation(); -+ void checkSeascapeOrientation(); -+ void checkVersion(); -+ void checkPdfId(); -+ void checkNoPdfId(); -+}; -+ -+void TestMetaData::checkStrings_data() -+{ -+ QTest::addColumn("key"); -+ QTest::addColumn("value"); -+ -+ QTest::newRow( "Author" ) << "Author" << "Brad Hards"; -+ QTest::newRow( "Title" ) << "Title" << "Two pages"; -+ QTest::newRow( "Subject" ) << "Subject" -+ << "A two page layout for poppler testing"; -+ QTest::newRow( "Keywords" ) << "Keywords" << "Qt4 bindings"; -+ QTest::newRow( "Creator" ) << "Creator" << "iText: cgpdftops CUPS filter"; -+ QTest::newRow( "Producer" ) << "Producer" << "Acrobat Distiller 7.0 for Macintosh"; -+} -+ -+void TestMetaData::checkStrings() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/doublepage.pdf"); -+ QVERIFY( doc ); -+ -+ QFETCH( QString, key ); -+ QFETCH( QString, value ); -+ QCOMPARE( doc->info(key), value ); -+ -+ delete doc; -+} -+ -+void TestMetaData::checkStrings2_data() -+{ -+ QTest::addColumn("key"); -+ QTest::addColumn("value"); -+ -+ QTest::newRow( "Title" ) << "Title" << "Malaga hotels"; -+ QTest::newRow( "Author" ) << "Author" << "Brad Hards"; -+ QTest::newRow( "Creator" ) << "Creator" << "Safari: cgpdftops CUPS filter"; -+ QTest::newRow( "Producer" ) << "Producer" << "Acrobat Distiller 7.0 for Macintosh"; -+ QTest::newRow( "Keywords" ) << "Keywords" << "First\rSecond\rthird"; -+ QTest::newRow( "Custom1" ) << "Custom1" << "CustomValue1"; -+ QTest::newRow( "Custom2" ) << "Custom2" << "CustomValue2"; -+} -+ -+void TestMetaData::checkStrings2() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/truetype.pdf"); -+ QVERIFY( doc ); -+ -+ QFETCH( QString, key ); -+ QFETCH( QString, value ); -+ QCOMPARE( doc->info(key), value ); -+ -+ delete doc; -+} -+ -+void TestMetaData::checkStringKeys() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/truetype.pdf"); -+ QVERIFY( doc ); -+ -+ QStringList keyList; -+ keyList << "Title" << "Author" << "Creator" << "Keywords" << "CreationDate"; -+ keyList << "Producer" << "ModDate" << "Custom1" << "Custom2"; -+ keyList.sort(); -+ QStringList keysInDoc = doc->infoKeys(); -+ keysInDoc.sort(); -+ QCOMPARE( keysInDoc, keyList ); -+ -+ delete doc; -+} -+ -+void TestMetaData::checkLinearised() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/orientation.pdf"); -+ QVERIFY( doc ); -+ -+ QVERIFY( doc->isLinearized() ); -+ -+ delete doc; -+ -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/truetype.pdf"); -+ QVERIFY( doc ); -+ QCOMPARE( doc->isLinearized(), false ); -+ -+ delete doc; -+} -+ -+void TestMetaData::checkPortraitOrientation() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/orientation.pdf"); -+ QVERIFY( doc ); -+ -+ Poppler::Page *page = doc->page(0); -+ QCOMPARE( page->orientation(), Poppler::Page::Portrait ); -+ -+ delete page; -+ delete doc; -+} -+ -+void TestMetaData::checkNumPages() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/doublepage.pdf"); -+ QVERIFY( doc ); -+ QCOMPARE( doc->numPages(), 2 ); -+ -+ delete doc; -+ -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/truetype.pdf"); -+ QVERIFY( doc ); -+ QCOMPARE( doc->numPages(), 1 ); -+ -+ delete doc; -+} -+ -+void TestMetaData::checkDate() -+{ -+ Poppler::Document *doc; -+ -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/truetype.pdf"); -+ QVERIFY( doc ); -+ QCOMPARE( doc->date("ModDate"), QDateTime(QDate(2005, 12, 5), QTime(9,44,46), Qt::UTC ) ); -+ QCOMPARE( doc->date("CreationDate"), QDateTime(QDate(2005, 8, 13), QTime(1,12,11), Qt::UTC ) ); -+ -+ delete doc; -+} -+ -+void TestMetaData::checkPageSize() -+{ -+ Poppler::Document *doc; -+ -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/truetype.pdf"); -+ QVERIFY( doc ); -+ Poppler::Page *page = doc->page(0); -+ QCOMPARE( page->pageSize(), QSize(595, 842) ); -+ QCOMPARE( page->pageSizeF(), QSizeF(595.22, 842) ); -+ -+ delete page; -+ delete doc; -+} -+ -+ -+void TestMetaData::checkLandscapeOrientation() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/orientation.pdf"); -+ QVERIFY( doc ); -+ -+ Poppler::Page *page = doc->page(1); -+ QCOMPARE( page->orientation(), Poppler::Page::Landscape ); -+ -+ delete page; -+ delete doc; -+} -+ -+void TestMetaData::checkUpsideDownOrientation() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/orientation.pdf"); -+ QVERIFY( doc ); -+ -+ Poppler::Page *page = doc->page(2); -+ QCOMPARE( page->orientation(), Poppler::Page::UpsideDown ); -+ -+ delete page; -+ delete doc; -+} -+ -+void TestMetaData::checkSeascapeOrientation() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/orientation.pdf"); -+ QVERIFY( doc ); -+ -+ Poppler::Page *page = doc->page(3); -+ QCOMPARE( page->orientation(), Poppler::Page::Seascape ); -+ -+ delete page; -+ delete doc; -+} -+ -+void TestMetaData::checkVersion() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/doublepage.pdf"); -+ QVERIFY( doc ); -+ -+ QCOMPARE( doc->pdfVersion(), 1.6 ); -+ int major = 0, minor = 0; -+ doc->getPdfVersion( &major, &minor ); -+ QCOMPARE( major, 1 ); -+ QCOMPARE( minor, 6 ); -+ -+ delete doc; -+} -+ -+void TestMetaData::checkPdfId() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/A6EmbeddedFiles.pdf"); -+ QVERIFY( doc ); -+ -+ const QByteArray referencePermanentId( "00C9D5B6D8FB11D7A902003065D630AA" ); -+ const QByteArray referenceUpdateId( "39AECAE6D8FB11D7A902003065D630AA" ); -+ -+ { -+ // no IDs wanted, just existance check -+ QVERIFY( doc->getPdfId( 0, 0 ) ); -+ } -+ { -+ // only permanent ID -+ QByteArray permanentId; -+ QVERIFY( doc->getPdfId( &permanentId, 0 ) ); -+ QCOMPARE( permanentId.toUpper(), referencePermanentId ); -+ } -+ { -+ // only update ID -+ QByteArray updateId; -+ QVERIFY( doc->getPdfId( 0, &updateId ) ); -+ QCOMPARE( updateId.toUpper(), referenceUpdateId ); -+ } -+ { -+ // both IDs -+ QByteArray permanentId; -+ QByteArray updateId; -+ QVERIFY( doc->getPdfId( &permanentId, &updateId ) ); -+ QCOMPARE( permanentId.toUpper(), referencePermanentId ); -+ QCOMPARE( updateId.toUpper(), referenceUpdateId ); -+ } -+ -+ delete doc; -+} -+ -+void TestMetaData::checkNoPdfId() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/WithActualText.pdf"); -+ QVERIFY( doc ); -+ -+ QVERIFY( !doc->getPdfId( 0, 0 ) ); -+ -+ delete doc; -+} -+ -+QTEST_MAIN(TestMetaData) -+#include "check_metadata.moc" -+ -diff --git a/qt4/tests/check_optcontent.cpp b/qt4/tests/check_optcontent.cpp -new file mode 100644 -index 00000000..2de29952 ---- /dev/null -+++ b/qt4/tests/check_optcontent.cpp -@@ -0,0 +1,446 @@ -+#include -+ -+#include "PDFDoc.h" -+#include "GlobalParams.h" -+ -+#include -+ -+class TestOptionalContent: public QObject -+{ -+ Q_OBJECT -+private slots: -+ void checkVisPolicy(); -+ void checkNestedLayers(); -+ void checkNoOptionalContent(); -+ void checkIsVisible(); -+ void checkVisibilitySetting(); -+ void checkRadioButtons(); -+}; -+ -+void TestOptionalContent::checkVisPolicy() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/vis_policy_test.pdf"); -+ QVERIFY( doc ); -+ -+ QVERIFY( doc->hasOptionalContent() ); -+ -+ Poppler::OptContentModel *optContent = doc->optionalContentModel(); -+ QModelIndex index; -+ index = optContent->index( 0, 0, QModelIndex() ); -+ QCOMPARE( optContent->data( index, Qt::DisplayRole ).toString(), QString( "A" ) ); -+ QCOMPARE( static_cast( optContent->data( index, Qt::CheckStateRole ).toInt() ), Qt::Checked ); -+ index = optContent->index( 1, 0, QModelIndex() ); -+ QCOMPARE( optContent->data( index, Qt::DisplayRole ).toString(), QString( "B" ) ); -+ QCOMPARE( static_cast( optContent->data( index, Qt::CheckStateRole ).toInt() ), Qt::Checked ); -+ -+ delete doc; -+} -+ -+void TestOptionalContent::checkNestedLayers() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/NestedLayers.pdf"); -+ QVERIFY( doc ); -+ -+ QVERIFY( doc->hasOptionalContent() ); -+ -+ Poppler::OptContentModel *optContent = doc->optionalContentModel(); -+ QModelIndex index; -+ -+ index = optContent->index( 0, 0, QModelIndex() ); -+ QCOMPARE( optContent->data( index, Qt::DisplayRole ).toString(), QString( "Black Text and Green Snow" ) ); -+ QCOMPARE( static_cast( optContent->data( index, Qt::CheckStateRole ).toInt() ), Qt::Unchecked ); -+ -+ index = optContent->index( 1, 0, QModelIndex() ); -+ QCOMPARE( optContent->data( index, Qt::DisplayRole ).toString(), QString( "Mountains and Image" ) ); -+ QCOMPARE( static_cast( optContent->data( index, Qt::CheckStateRole ).toInt() ), Qt::Checked ); -+ -+ // This is a sub-item of "Mountains and Image" -+ QModelIndex subindex = optContent->index( 0, 0, index ); -+ QCOMPARE( optContent->data( subindex, Qt::DisplayRole ).toString(), QString( "Image" ) ); -+ QCOMPARE( static_cast( optContent->data( index, Qt::CheckStateRole ).toInt() ), Qt::Checked ); -+ -+ index = optContent->index( 2, 0, QModelIndex() ); -+ QCOMPARE( optContent->data( index, Qt::DisplayRole ).toString(), QString( "Starburst" ) ); -+ QCOMPARE( static_cast( optContent->data( index, Qt::CheckStateRole ).toInt() ), Qt::Checked ); -+ -+ index = optContent->index( 3, 0, QModelIndex() ); -+ QCOMPARE( optContent->data( index, Qt::DisplayRole ).toString(), QString( "Watermark" ) ); -+ QCOMPARE( static_cast( optContent->data( index, Qt::CheckStateRole ).toInt() ), Qt::Unchecked ); -+ -+ delete doc; -+} -+ -+void TestOptionalContent::checkNoOptionalContent() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/orientation.pdf"); -+ QVERIFY( doc ); -+ -+ QCOMPARE( doc->hasOptionalContent(), false ); -+ -+ delete doc; -+} -+ -+void TestOptionalContent::checkIsVisible() -+{ -+ GooString *fileName = new GooString(TESTDATADIR "/unittestcases/vis_policy_test.pdf"); -+ globalParams = std::make_unique(); -+ PDFDoc *doc = new PDFDoc( fileName ); -+ QVERIFY( doc ); -+ -+ OCGs *ocgs = doc->getOptContentConfig(); -+ QVERIFY( ocgs ); -+ -+ XRef *xref = doc->getXRef(); -+ -+ Object obj; -+ -+ // In this test, both Ref(21,0) and Ref(2,0) are set to On -+ -+ // AnyOn, one element array: -+ // 22 0 obj<>endobj -+ obj = xref->fetch( { 22, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QVERIFY( ocgs->optContentIsVisible( &obj ) ); -+ -+ // Same again, looking for any leaks or dubious free()'s -+ obj = xref->fetch( { 22, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QVERIFY( ocgs->optContentIsVisible( &obj ) ); -+ -+ // AnyOff, one element array: -+ // 29 0 obj<>endobj -+ obj = xref->fetch( { 29, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ // AllOn, one element array: -+ // 36 0 obj<>endobj -+ obj = xref->fetch( { 36, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), true ); -+ -+ -+ // AllOff, one element array: -+ // 43 0 obj<>endobj -+ obj = xref->fetch( { 43, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ // AnyOn, multi-element array: -+ // 50 0 obj<>endobj -+ obj = xref->fetch( { 50, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), true ); -+ -+ // AnyOff, multi-element array: -+ // 57 0 obj<>endobj -+ obj = xref->fetch( { 57, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ // AllOn, multi-element array: -+ // 64 0 obj<>endobj -+ obj = xref->fetch( { 64, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), true ); -+ -+ // AllOff, multi-element array: -+ // 71 0 obj<>endobj -+ obj = xref->fetch( { 71, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ delete doc; -+ globalParams.reset(); -+} -+ -+void TestOptionalContent::checkVisibilitySetting() -+{ -+ globalParams = std::make_unique(); -+ GooString *fileName = new GooString(TESTDATADIR "/unittestcases/vis_policy_test.pdf"); -+ PDFDoc *doc = new PDFDoc( fileName ); -+ QVERIFY( doc ); -+ -+ OCGs *ocgs = doc->getOptContentConfig(); -+ QVERIFY( ocgs ); -+ -+ XRef *xref = doc->getXRef(); -+ -+ Object obj; -+ -+ // In this test, both Ref(21,0) and Ref(28,0) start On, -+ // based on the file settings -+ Object ref21obj( { 21, 0 } ); -+ Ref ref21 = ref21obj.getRef(); -+ OptionalContentGroup *ocgA = ocgs->findOcgByRef( ref21 ); -+ QVERIFY( ocgA ); -+ -+ QVERIFY( (ocgA->getName()->cmp("A")) == 0 ); -+ QCOMPARE( ocgA->getState(), OptionalContentGroup::On ); -+ -+ Object ref28obj( { 28, 0 } ); -+ Ref ref28 = ref28obj.getRef(); -+ OptionalContentGroup *ocgB = ocgs->findOcgByRef( ref28 ); -+ QVERIFY( ocgB ); -+ -+ QVERIFY( (ocgB->getName()->cmp("B")) == 0 ); -+ QCOMPARE( ocgB->getState(), OptionalContentGroup::On ); -+ -+ // turn one Off -+ ocgA->setState( OptionalContentGroup::Off ); -+ -+ // AnyOn, one element array: -+ // 22 0 obj<>endobj -+ obj = xref->fetch( { 22, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ // Same again, looking for any leaks or dubious free()'s -+ obj = xref->fetch( { 22, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ // AnyOff, one element array: -+ // 29 0 obj<>endobj -+ obj = xref->fetch( { 29, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), true ); -+ -+ // AllOn, one element array: -+ // 36 0 obj<>endobj -+ obj = xref->fetch( { 36, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), true ); -+ -+ // AllOff, one element array: -+ // 43 0 obj<>endobj -+ obj = xref->fetch( { 43, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ // AnyOn, multi-element array: -+ // 50 0 obj<>endobj -+ obj = xref->fetch( { 50, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), true ); -+ -+ // AnyOff, multi-element array: -+ // 57 0 obj<>endobj -+ obj = xref->fetch( { 57, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), true ); -+ -+ // AllOn, multi-element array: -+ // 64 0 obj<>endobj -+ obj = xref->fetch( { 64, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ // AllOff, multi-element array: -+ // 71 0 obj<>endobj -+ obj = xref->fetch( { 71, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ -+ // Turn the other one off as well (i.e. both are Off) -+ ocgB->setState(OptionalContentGroup::Off); -+ -+ // AnyOn, one element array: -+ // 22 0 obj<>endobj -+ obj = xref->fetch( { 22, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ // Same again, looking for any leaks or dubious free()'s -+ obj = xref->fetch( { 22, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ // AnyOff, one element array: -+ // 29 0 obj<>endobj -+ obj = xref->fetch( { 29, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), true ); -+ -+ // AllOn, one element array: -+ // 36 0 obj<>endobj -+ obj = xref->fetch( { 36, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ // AllOff, one element array: -+ // 43 0 obj<>endobj -+ obj = xref->fetch( { 43, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), true ); -+ -+ // AnyOn, multi-element array: -+ // 50 0 obj<>endobj -+ obj = xref->fetch( { 50, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ // AnyOff, multi-element array: -+ // 57 0 obj<>endobj -+ obj = xref->fetch( { 57, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), true ); -+ -+ // AllOn, multi-element array: -+ // 64 0 obj<>endobj -+ obj = xref->fetch( { 64, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ // AllOff, multi-element array: -+ // 71 0 obj<>endobj -+ obj = xref->fetch( { 71, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), true ); -+ -+ -+ // Turn the first one on again (21 is On, 28 is Off) -+ ocgA->setState(OptionalContentGroup::On); -+ -+ // AnyOn, one element array: -+ // 22 0 obj<>endobj -+ obj = xref->fetch( { 22, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), true ); -+ -+ // Same again, looking for any leaks or dubious free()'s -+ obj = xref->fetch( { 22, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), true ); -+ -+ // AnyOff, one element array: -+ // 29 0 obj<>endobj -+ obj = xref->fetch( { 29, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ // AllOn, one element array: -+ // 36 0 obj<>endobj -+ obj = xref->fetch( { 36, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ // AllOff, one element array: -+ // 43 0 obj<>endobj -+ obj = xref->fetch( { 43, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), true ); -+ -+ // AnyOn, multi-element array: -+ // 50 0 obj<>endobj -+ obj = xref->fetch( { 50, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), true ); -+ -+ // AnyOff, multi-element array: -+ // 57 0 obj<>endobj -+ obj = xref->fetch( { 57, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), true ); -+ -+ // AllOn, multi-element array: -+ // 64 0 obj<>endobj -+ obj = xref->fetch( { 64, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ // AllOff, multi-element array: -+ // 71 0 obj<>endobj -+ obj = xref->fetch( { 71, 0 } ); -+ QVERIFY( obj.isDict() ); -+ QCOMPARE( ocgs->optContentIsVisible( &obj ), false ); -+ -+ delete doc; -+ globalParams.reset(); -+} -+ -+void TestOptionalContent::checkRadioButtons() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/ClarityOCGs.pdf"); -+ QVERIFY( doc ); -+ -+ QVERIFY( doc->hasOptionalContent() ); -+ -+ Poppler::OptContentModel *optContent = doc->optionalContentModel(); -+ QModelIndex index; -+ -+ index = optContent->index( 0, 0, QModelIndex() ); -+ QCOMPARE( optContent->data( index, Qt::DisplayRole ).toString(), QString( "Languages" ) ); -+ QCOMPARE( static_cast( optContent->data( index, Qt::CheckStateRole ).toInt() ), Qt::Unchecked ); -+ -+ // These are sub-items of the "Languages" label -+ QModelIndex subindex = optContent->index( 0, 0, index ); -+ QCOMPARE( optContent->data( subindex, Qt::DisplayRole ).toString(), QString( "English" ) ); -+ QCOMPARE( static_cast( optContent->data( subindex, Qt::CheckStateRole ).toInt() ), Qt::Checked ); -+ -+ subindex = optContent->index( 1, 0, index ); -+ QCOMPARE( optContent->data( subindex, Qt::DisplayRole ).toString(), QString( "French" ) ); -+ QCOMPARE( static_cast( optContent->data( subindex, Qt::CheckStateRole ).toInt() ), Qt::Unchecked ); -+ -+ subindex = optContent->index( 2, 0, index ); -+ QCOMPARE( optContent->data( subindex, Qt::DisplayRole ).toString(), QString( "Japanese" ) ); -+ QCOMPARE( static_cast( optContent->data( subindex, Qt::CheckStateRole ).toInt() ), Qt::Unchecked ); -+ -+ // RBGroup of languages, so turning on Japanese should turn off English -+ QVERIFY( optContent->setData( subindex, QVariant( true ), Qt::CheckStateRole ) ); -+ -+ subindex = optContent->index( 0, 0, index ); -+ QCOMPARE( optContent->data( subindex, Qt::DisplayRole ).toString(), QString( "English" ) ); -+ QCOMPARE( static_cast( optContent->data( subindex, Qt::CheckStateRole ).toInt() ), Qt::Unchecked ); -+ -+ subindex = optContent->index( 2, 0, index ); -+ QCOMPARE( optContent->data( subindex, Qt::DisplayRole ).toString(), QString( "Japanese" ) ); -+ QCOMPARE( static_cast( optContent->data( subindex, Qt::CheckStateRole ).toInt() ), Qt::Checked ); -+ -+ subindex = optContent->index( 1, 0, index ); -+ QCOMPARE( optContent->data( subindex, Qt::DisplayRole ).toString(), QString( "French" ) ); -+ QCOMPARE( static_cast( optContent->data( subindex, Qt::CheckStateRole ).toInt() ), Qt::Unchecked ); -+ -+ // and turning on French should turn off Japanese -+ QVERIFY( optContent->setData( subindex, QVariant( true ), Qt::CheckStateRole ) ); -+ -+ subindex = optContent->index( 0, 0, index ); -+ QCOMPARE( optContent->data( subindex, Qt::DisplayRole ).toString(), QString( "English" ) ); -+ QCOMPARE( static_cast( optContent->data( subindex, Qt::CheckStateRole ).toInt() ), Qt::Unchecked ); -+ -+ subindex = optContent->index( 2, 0, index ); -+ QCOMPARE( optContent->data( subindex, Qt::DisplayRole ).toString(), QString( "Japanese" ) ); -+ QCOMPARE( static_cast( optContent->data( subindex, Qt::CheckStateRole ).toInt() ), Qt::Unchecked ); -+ -+ subindex = optContent->index( 1, 0, index ); -+ QCOMPARE( optContent->data( subindex, Qt::DisplayRole ).toString(), QString( "French" ) ); -+ QCOMPARE( static_cast( optContent->data( subindex, Qt::CheckStateRole ).toInt() ), Qt::Checked ); -+ -+ -+ // and turning off French should leave them all off -+ QVERIFY( optContent->setData( subindex, QVariant( false ), Qt::CheckStateRole ) ); -+ -+ subindex = optContent->index( 0, 0, index ); -+ QCOMPARE( optContent->data( subindex, Qt::DisplayRole ).toString(), QString( "English" ) ); -+ QCOMPARE( static_cast( optContent->data( subindex, Qt::CheckStateRole ).toInt() ), Qt::Unchecked ); -+ -+ subindex = optContent->index( 2, 0, index ); -+ QCOMPARE( optContent->data( subindex, Qt::DisplayRole ).toString(), QString( "Japanese" ) ); -+ QCOMPARE( static_cast( optContent->data( subindex, Qt::CheckStateRole ).toInt() ), Qt::Unchecked ); -+ -+ subindex = optContent->index( 1, 0, index ); -+ QCOMPARE( optContent->data( subindex, Qt::DisplayRole ).toString(), QString( "French" ) ); -+ QCOMPARE( static_cast( optContent->data( subindex, Qt::CheckStateRole ).toInt() ), Qt::Unchecked ); -+ -+ delete doc; -+} -+ -+QTEST_MAIN(TestOptionalContent) -+ -+#include "check_optcontent.moc" -+ -diff --git a/qt4/tests/check_pagelabelinfo.cpp b/qt4/tests/check_pagelabelinfo.cpp -new file mode 100644 -index 00000000..4eb1ec36 ---- /dev/null -+++ b/qt4/tests/check_pagelabelinfo.cpp -@@ -0,0 +1,43 @@ -+#include -+ -+#include "PageLabelInfo_p.h" -+ -+class TestPageLabelInfo : public QObject -+{ -+ Q_OBJECT -+private slots: -+ void testToRoman(); -+ void testFromRoman(); -+ void testToLatin(); -+ void testFromLatin(); -+}; -+ -+void TestPageLabelInfo::testToRoman() -+{ -+ GooString str; -+ toRoman(177, &str, false); -+ QCOMPARE (str.c_str(), "clxxvii"); -+} -+ -+void TestPageLabelInfo::testFromRoman() -+{ -+ GooString roman("clxxvii"); -+ QCOMPARE(fromRoman(roman.c_str()), 177); -+} -+ -+void TestPageLabelInfo::testToLatin() -+{ -+ GooString str; -+ toLatin(54, &str, false); -+ QCOMPARE(str.c_str(), "bbb"); -+} -+ -+void TestPageLabelInfo::testFromLatin() -+{ -+ GooString latin("ddd"); -+ QCOMPARE(fromLatin(latin.c_str()), 56); -+} -+ -+QTEST_MAIN(TestPageLabelInfo) -+#include "check_pagelabelinfo.moc" -+ -diff --git a/qt4/tests/check_pagelayout.cpp b/qt4/tests/check_pagelayout.cpp -new file mode 100644 -index 00000000..6108f886 ---- /dev/null -+++ b/qt4/tests/check_pagelayout.cpp -@@ -0,0 +1,49 @@ -+#include -+ -+#include -+ -+class TestPageLayout: public QObject -+{ -+ Q_OBJECT -+private slots: -+ void checkNone(); -+ void checkSingle(); -+ void checkFacing(); -+}; -+ -+void TestPageLayout::checkNone() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/UseNone.pdf"); -+ QVERIFY( doc ); -+ -+ QCOMPARE( doc->pageLayout(), Poppler::Document::NoLayout ); -+ -+ delete doc; -+} -+ -+void TestPageLayout::checkSingle() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/FullScreen.pdf"); -+ QVERIFY( doc ); -+ -+ QCOMPARE( doc->pageLayout(), Poppler::Document::SinglePage ); -+ -+ delete doc; -+} -+ -+void TestPageLayout::checkFacing() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/doublepage.pdf"); -+ QVERIFY( doc ); -+ -+ QCOMPARE( doc->pageLayout(), Poppler::Document::TwoPageRight ); -+ -+ delete doc; -+} -+ -+QTEST_MAIN(TestPageLayout) -+#include "check_pagelayout.moc" -+ -diff --git a/qt4/tests/check_pagemode.cpp b/qt4/tests/check_pagemode.cpp -new file mode 100644 -index 00000000..0565fe20 ---- /dev/null -+++ b/qt4/tests/check_pagemode.cpp -@@ -0,0 +1,73 @@ -+#include -+ -+#include -+ -+class TestPageMode: public QObject -+{ -+ Q_OBJECT -+private slots: -+ void checkNone(); -+ void checkFullScreen(); -+ void checkAttachments(); -+ void checkThumbs(); -+ void checkOC(); -+}; -+ -+void TestPageMode::checkNone() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/UseNone.pdf"); -+ QVERIFY( doc ); -+ -+ QCOMPARE( doc->pageMode(), Poppler::Document::UseNone ); -+ -+ delete doc; -+} -+ -+void TestPageMode::checkFullScreen() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/FullScreen.pdf"); -+ QVERIFY( doc ); -+ -+ QCOMPARE( doc->pageMode(), Poppler::Document::FullScreen ); -+ -+ delete doc; -+} -+ -+void TestPageMode::checkAttachments() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/UseAttachments.pdf"); -+ QVERIFY( doc ); -+ -+ QCOMPARE( doc->pageMode(), Poppler::Document::UseAttach ); -+ -+ delete doc; -+} -+ -+void TestPageMode::checkThumbs() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/UseThumbs.pdf"); -+ QVERIFY( doc ); -+ -+ QCOMPARE( doc->pageMode(), Poppler::Document::UseThumbs ); -+ -+ delete doc; -+} -+ -+void TestPageMode::checkOC() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/UseOC.pdf"); -+ QVERIFY( doc ); -+ -+ QCOMPARE( doc->pageMode(), Poppler::Document::UseOC ); -+ -+ delete doc; -+} -+ -+QTEST_MAIN(TestPageMode) -+#include "check_pagemode.moc" -+ -diff --git a/qt4/tests/check_password.cpp b/qt4/tests/check_password.cpp -new file mode 100644 -index 00000000..4c7dcd1c ---- /dev/null -+++ b/qt4/tests/check_password.cpp -@@ -0,0 +1,88 @@ -+#include -+ -+#include -+ -+class TestPassword: public QObject -+{ -+ Q_OBJECT -+private slots: -+ void password1(); -+ void password1a(); -+ void password2(); -+ void password2a(); -+ void password2b(); -+ void password3(); -+}; -+ -+ -+// BUG:4557 -+void TestPassword::password1() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(QString::fromUtf8(TESTDATADIR "/unittestcases/Gday garçon - open.pdf"), "", QString::fromUtf8("garçon").toLatin1() ); -+ QVERIFY( doc ); -+ QVERIFY( !doc->isLocked() ); -+ -+ delete doc; -+} -+ -+ -+void TestPassword::password1a() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(QString::fromUtf8(TESTDATADIR "/unittestcases/Gday garçon - open.pdf") ); -+ QVERIFY( doc ); -+ QVERIFY( doc->isLocked() ); -+ QVERIFY( !doc->unlock( "", QString::fromUtf8("garçon").toLatin1() ) ); -+ QVERIFY( !doc->isLocked() ); -+ -+ delete doc; -+} -+ -+void TestPassword::password2() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(QString::fromUtf8(TESTDATADIR "/unittestcases/Gday garçon - owner.pdf"), QString::fromUtf8("garçon").toLatin1(), "" ); -+ QVERIFY( doc ); -+ QVERIFY( !doc->isLocked() ); -+ -+ delete doc; -+} -+ -+void TestPassword::password2a() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(QString::fromUtf8(TESTDATADIR "/unittestcases/Gday garçon - owner.pdf"), QString::fromUtf8("garçon").toLatin1() ); -+ QVERIFY( doc ); -+ QVERIFY( !doc->isLocked() ); -+ -+ delete doc; -+} -+ -+void TestPassword::password2b() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(QString::fromUtf8(TESTDATADIR "/unittestcases/Gday garçon - owner.pdf") ); -+ QVERIFY( doc ); -+ QVERIFY( !doc->isLocked() ); -+ QVERIFY( !doc->unlock( QString::fromUtf8("garçon").toLatin1(), "" ) ); -+ QVERIFY( !doc->isLocked() ); -+ -+ delete doc; -+} -+ -+void TestPassword::password3() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load( QString::fromUtf8(TESTDATADIR "/unittestcases/PasswordEncrypted.pdf") ); -+ QVERIFY( doc ); -+ QVERIFY( doc->isLocked() ); -+ QVERIFY( !doc->unlock( "", "password" ) ); -+ QVERIFY( !doc->isLocked() ); -+ -+ delete doc; -+} -+ -+QTEST_MAIN(TestPassword) -+#include "check_password.moc" -+ -diff --git a/qt4/tests/check_permissions.cpp b/qt4/tests/check_permissions.cpp -new file mode 100644 -index 00000000..a3f3bdc6 ---- /dev/null -+++ b/qt4/tests/check_permissions.cpp -@@ -0,0 +1,44 @@ -+#include -+ -+#include -+ -+class TestPermissions: public QObject -+{ -+ Q_OBJECT -+private slots: -+ void permissions1(); -+}; -+ -+void TestPermissions::permissions1() -+{ -+ Poppler::Document *doc; -+ doc = Poppler::Document::load(TESTDATADIR "/unittestcases/orientation.pdf"); -+ QVERIFY( doc ); -+ -+ // we are allowed to print -+ QVERIFY( doc->okToPrint() ); -+ -+ // we are not allowed to change -+ QVERIFY( !(doc->okToChange()) ); -+ -+ // we are not allowed to copy or extract content -+ QVERIFY( !(doc->okToCopy()) ); -+ -+ // we are not allowed to print at high resolution -+ QVERIFY( !(doc->okToPrintHighRes()) ); -+ -+ // we are not allowed to fill forms -+ QVERIFY( !(doc->okToFillForm()) ); -+ -+ // we are allowed to extract content for accessibility -+ QVERIFY( doc->okToExtractForAccessibility() ); -+ -+ // we are allowed to assemble this document -+ QVERIFY( doc->okToAssemble() ); -+ -+ delete doc; -+} -+ -+QTEST_MAIN(TestPermissions) -+#include "check_permissions.moc" -+ -diff --git a/qt4/tests/check_search.cpp b/qt4/tests/check_search.cpp -new file mode 100644 -index 00000000..99659e04 ---- /dev/null -+++ b/qt4/tests/check_search.cpp -@@ -0,0 +1,175 @@ -+#include -+ -+#include -+ -+class TestSearch: public QObject -+{ -+ Q_OBJECT -+private slots: -+ void bug7063(); -+ void testNextAndPrevious(); -+ void testWholeWordsOnly(); -+}; -+ -+void TestSearch::bug7063() -+{ -+ QScopedPointer< Poppler::Document > document(Poppler::Document::load(TESTDATADIR "/unittestcases/bug7063.pdf")); -+ QVERIFY( document ); -+ -+ QScopedPointer< Poppler::Page > page(document->page(0)); -+ QVERIFY( page ); -+ -+ QRectF pageRegion( QPointF(0,0), page->pageSize() ); -+ QCOMPARE( page->search(QString("non-ascii:"), pageRegion, Poppler::Page::FromTop, Poppler::Page::CaseSensitive), true ); -+ -+ QCOMPARE( page->search(QString("Ascii"), pageRegion, Poppler::Page::FromTop, Poppler::Page::CaseSensitive), false ); -+ QCOMPARE( page->search(QString("Ascii"), pageRegion, Poppler::Page::FromTop, Poppler::Page::CaseInsensitive), true ); -+ -+ QCOMPARE( page->search(QString("latin1:"), pageRegion, Poppler::Page::FromTop, Poppler::Page::CaseSensitive), false ); -+ -+ QCOMPARE( page->search(QString::fromUtf8("é"), pageRegion, Poppler::Page::FromTop, Poppler::Page::CaseSensitive), true ); -+ QCOMPARE( page->search(QString::fromUtf8("à"), pageRegion, Poppler::Page::FromTop, Poppler::Page::CaseSensitive), true ); -+ QCOMPARE( page->search(QString::fromUtf8("ç"), pageRegion, Poppler::Page::FromTop, Poppler::Page::CaseSensitive), true ); -+ QCOMPARE( page->search(QString::fromUtf8("search \"é\", \"à\" or \"ç\""), pageRegion, Poppler::Page::FromTop, Poppler::Page::CaseSensitive), true ); -+ QCOMPARE( page->search(QString::fromUtf8("¥µ©"), pageRegion, Poppler::Page::FromTop, Poppler::Page::CaseSensitive), true ); -+ QCOMPARE( page->search(QString::fromUtf8("¥©"), pageRegion, Poppler::Page::FromTop, Poppler::Page::CaseSensitive), false ); -+ -+ double rectLeft = 0.0, rectTop = 0.0, rectRight = page->pageSizeF().width(), rectBottom = page->pageSizeF().height(); -+ -+ QCOMPARE( page->search(QString("non-ascii:"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::FromTop), true ); -+ -+ QCOMPARE( page->search(QString("Ascii"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::FromTop), false ); -+ QCOMPARE( page->search(QString("Ascii"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::FromTop, Poppler::Page::IgnoreCase), true ); -+ -+ QCOMPARE( page->search(QString("latin1:"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::FromTop), false ); -+ -+ QCOMPARE( page->search(QString::fromUtf8("é"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::FromTop), true ); -+ QCOMPARE( page->search(QString::fromUtf8("à"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::FromTop), true ); -+ QCOMPARE( page->search(QString::fromUtf8("ç"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::FromTop), true ); -+ QCOMPARE( page->search(QString::fromUtf8("search \"é\", \"à\" or \"ç\""), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::FromTop), true ); -+ QCOMPARE( page->search(QString::fromUtf8("¥µ©"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::FromTop), true ); -+ QCOMPARE( page->search(QString::fromUtf8("¥©"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::FromTop), false ); -+} -+ -+void TestSearch::testNextAndPrevious() -+{ -+ QScopedPointer< Poppler::Document > document(Poppler::Document::load(TESTDATADIR "/unittestcases/xr01.pdf")); -+ QVERIFY( document ); -+ -+ QScopedPointer< Poppler::Page > page(document->page(0)); -+ QVERIFY( page ); -+ -+ QRectF region( QPointF(0,0), page->pageSize() ); -+ -+ QCOMPARE( page->search(QString("is"), region, Poppler::Page::FromTop, Poppler::Page::CaseSensitive), true ); -+ QVERIFY( qAbs(region.x() - 161.44) < 0.01 ); -+ QVERIFY( qAbs(region.y() - 127.85) < 0.01 ); -+ QVERIFY( qAbs(region.width() - 6.70) < 0.01 ); -+ QVERIFY( qAbs(region.height() - 8.85) < 0.01 ); -+ QCOMPARE( page->search(QString("is"), region, Poppler::Page::NextResult, Poppler::Page::CaseSensitive), true ); -+ QVERIFY( qAbs(region.x() - 171.46) < 0.01 ); -+ QVERIFY( qAbs(region.y() - 127.85) < 0.01 ); -+ QVERIFY( qAbs(region.width() - 6.70) < 0.01 ); -+ QVERIFY( qAbs(region.height() - 8.85) < 0.01 ); -+ QCOMPARE( page->search(QString("is"), region, Poppler::Page::NextResult, Poppler::Page::CaseSensitive), true ); -+ QVERIFY( qAbs(region.x() - 161.44) < 0.01 ); -+ QVERIFY( qAbs(region.y() - 139.81) < 0.01 ); -+ QVERIFY( qAbs(region.width() - 6.70) < 0.01 ); -+ QVERIFY( qAbs(region.height() - 8.85) < 0.01 ); -+ QCOMPARE( page->search(QString("is"), region, Poppler::Page::NextResult, Poppler::Page::CaseSensitive), true ); -+ QVERIFY( qAbs(region.x() - 171.46) < 0.01 ); -+ QVERIFY( qAbs(region.y() - 139.81) < 0.01 ); -+ QVERIFY( qAbs(region.width() - 6.70) < 0.01 ); -+ QVERIFY( qAbs(region.height() - 8.85) < 0.01 ); -+ QCOMPARE( page->search(QString("is"), region, Poppler::Page::NextResult, Poppler::Page::CaseSensitive), false ); -+ QCOMPARE( page->search(QString("is"), region, Poppler::Page::PreviousResult, Poppler::Page::CaseSensitive), true ); -+ QVERIFY( qAbs(region.x() - 161.44) < 0.01 ); -+ QVERIFY( qAbs(region.y() - 139.81) < 0.01 ); -+ QVERIFY( qAbs(region.width() - 6.70) < 0.01 ); -+ QVERIFY( qAbs(region.height() - 8.85) < 0.01 ); -+ QCOMPARE( page->search(QString("is"), region, Poppler::Page::PreviousResult, Poppler::Page::CaseSensitive), true ); -+ QVERIFY( qAbs(region.x() - 171.46) < 0.01 ); -+ QVERIFY( qAbs(region.y() - 127.85) < 0.01 ); -+ QVERIFY( qAbs(region.width() - 6.70) < 0.01 ); -+ QVERIFY( qAbs(region.height() - 8.85) < 0.01 ); -+ QCOMPARE( page->search(QString("is"), region, Poppler::Page::PreviousResult, Poppler::Page::CaseSensitive), true ); -+ QVERIFY( qAbs(region.x() - 161.44) < 0.01 ); -+ QVERIFY( qAbs(region.y() - 127.85) < 0.01 ); -+ QVERIFY( qAbs(region.width() - 6.70) < 0.01 ); -+ QVERIFY( qAbs(region.height() - 8.85) < 0.01 ); -+ QCOMPARE( page->search(QString("is"), region, Poppler::Page::PreviousResult, Poppler::Page::CaseSensitive), false ); -+ -+ double rectLeft = 0.0, rectTop = 0.0, rectRight = page->pageSizeF().width(), rectBottom = page->pageSizeF().height(); -+ -+ QCOMPARE( page->search(QString("is"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::FromTop), true ); -+ QVERIFY( qAbs(rectLeft - 161.44) < 0.01 ); -+ QVERIFY( qAbs(rectTop - 127.85) < 0.01 ); -+ QVERIFY( qAbs(rectRight - rectLeft - 6.70) < 0.01 ); -+ QVERIFY( qAbs(rectBottom - rectTop - 8.85) < 0.01 ); -+ QCOMPARE( page->search(QString("is"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::NextResult), true ); -+ QVERIFY( qAbs(rectLeft - 171.46) < 0.01 ); -+ QVERIFY( qAbs(rectTop - 127.85) < 0.01 ); -+ QVERIFY( qAbs(rectRight - rectLeft - 6.70) < 0.01 ); -+ QVERIFY( qAbs(rectBottom - rectTop - 8.85) < 0.01 ); -+ QCOMPARE( page->search(QString("is"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::NextResult), true ); -+ QVERIFY( qAbs(rectLeft - 161.44) < 0.01 ); -+ QVERIFY( qAbs(rectTop - 139.81) < 0.01 ); -+ QVERIFY( qAbs(rectRight - rectLeft - 6.70) < 0.01 ); -+ QVERIFY( qAbs(rectBottom - rectTop - 8.85) < 0.01 ); -+ QCOMPARE( page->search(QString("is"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::NextResult), true ); -+ QVERIFY( qAbs(rectLeft - 171.46) < 0.01 ); -+ QVERIFY( qAbs(rectTop - 139.81) < 0.01 ); -+ QVERIFY( qAbs(rectRight - rectLeft - 6.70) < 0.01 ); -+ QVERIFY( qAbs(rectBottom - rectTop - 8.85) < 0.01 ); -+ QCOMPARE( page->search(QString("is"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::NextResult), false ); -+ QCOMPARE( page->search(QString("is"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::PreviousResult), true ); -+ QVERIFY( qAbs(rectLeft - 161.44) < 0.01 ); -+ QVERIFY( qAbs(rectTop - 139.81) < 0.01 ); -+ QVERIFY( qAbs(rectRight - rectLeft - 6.70) < 0.01 ); -+ QVERIFY( qAbs(rectBottom - rectTop - 8.85) < 0.01 ); -+ QCOMPARE( page->search(QString("is"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::PreviousResult), true ); -+ QVERIFY( qAbs(rectLeft - 171.46) < 0.01 ); -+ QVERIFY( qAbs(rectTop - 127.85) < 0.01 ); -+ QVERIFY( qAbs(rectRight - rectLeft - 6.70) < 0.01 ); -+ QVERIFY( qAbs(rectBottom - rectTop - 8.85) < 0.01 ); -+ QCOMPARE( page->search(QString("is"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::PreviousResult), true ); -+ QVERIFY( qAbs(rectLeft - 161.44) < 0.01 ); -+ QVERIFY( qAbs(rectTop - 127.85) < 0.01 ); -+ QVERIFY( qAbs(rectRight - rectLeft - 6.70) < 0.01 ); -+ QVERIFY( qAbs(rectBottom - rectTop - 8.85) < 0.01 ); -+ QCOMPARE( page->search(QString("is"), rectLeft, rectTop, rectRight, rectBottom, Poppler::Page::PreviousResult), false ); -+} -+ -+void TestSearch::testWholeWordsOnly() -+{ -+ QScopedPointer< Poppler::Document > document(Poppler::Document::load(TESTDATADIR "/unittestcases/WithActualText.pdf")); -+ QVERIFY( document ); -+ -+ QScopedPointer< Poppler::Page > page(document->page(0)); -+ QVERIFY( page ); -+ -+ const Poppler::Page::SearchDirection direction = Poppler::Page::FromTop; -+ -+ const Poppler::Page::SearchFlags mode0 = 0; -+ const Poppler::Page::SearchFlags mode1 = Poppler::Page::IgnoreCase; -+ const Poppler::Page::SearchFlags mode2 = Poppler::Page::WholeWords; -+ const Poppler::Page::SearchFlags mode3 = Poppler::Page::IgnoreCase | Poppler::Page::WholeWords; -+ -+ double left, top, right, bottom; -+ -+ QCOMPARE( page->search(QLatin1String("brown"), left, top, right, bottom, direction, mode0), true ); -+ QCOMPARE( page->search(QLatin1String("brOwn"), left, top, right, bottom, direction, mode0), false ); -+ -+ QCOMPARE( page->search(QLatin1String("brOwn"), left, top, right, bottom, direction, mode1), true ); -+ QCOMPARE( page->search(QLatin1String("brawn"), left, top, right, bottom, direction, mode1), false ); -+ -+ QCOMPARE( page->search(QLatin1String("brown"), left, top, right, bottom, direction, mode2), true ); -+ QCOMPARE( page->search(QLatin1String("own"), left, top, right, bottom, direction, mode2), false ); -+ -+ QCOMPARE( page->search(QLatin1String("brOwn"), left, top, right, bottom, direction, mode3), true ); -+ QCOMPARE( page->search(QLatin1String("Own"), left, top, right, bottom, direction, mode3), false ); -+} -+ -+QTEST_MAIN(TestSearch) -+#include "check_search.moc" -+ -diff --git a/qt4/tests/check_strings.cpp b/qt4/tests/check_strings.cpp -new file mode 100644 -index 00000000..700ae9c2 ---- /dev/null -+++ b/qt4/tests/check_strings.cpp -@@ -0,0 +1,250 @@ -+/* -+ * Copyright (C) 2010, 2011, Pino Toscano -+ * -+ * 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 -+ -+#include -+#include -+ -+#include -+ -+Q_DECLARE_METATYPE(GooString*) -+Q_DECLARE_METATYPE(Unicode*) -+ -+class TestStrings : public QObject -+{ -+ Q_OBJECT -+ -+private slots: -+ void initTestCase(); -+ void cleanupTestCase(); -+ void check_unicodeToQString_data(); -+ void check_unicodeToQString(); -+ void check_UnicodeParsedString_data(); -+ void check_UnicodeParsedString(); -+ void check_QStringToUnicodeGooString_data(); -+ void check_QStringToUnicodeGooString(); -+ void check_QStringToGooString_data(); -+ void check_QStringToGooString(); -+ -+private: -+ GooString* newGooString(const char *s); -+ GooString* newGooString(const char *s, int l); -+ -+ QVector m_gooStrings; -+}; -+ -+void TestStrings::initTestCase() -+{ -+ qRegisterMetaType("GooString*"); -+ qRegisterMetaType("Unicode*"); -+ -+ globalParams = std::make_unique(); -+} -+ -+void TestStrings::cleanupTestCase() -+{ -+ qDeleteAll(m_gooStrings); -+ -+ globalParams.reset(); -+} -+ -+void TestStrings::check_unicodeToQString_data() -+{ -+ QTest::addColumn("data"); -+ QTest::addColumn("length"); -+ QTest::addColumn("result"); -+ -+ { -+ const int l = 1; -+ Unicode *u = new Unicode[l]; -+ u[0] = int('a'); -+ QTest::newRow("a") << u << l << QString::fromUtf8("a"); -+ } -+ { -+ const int l = 1; -+ Unicode *u = new Unicode[l]; -+ u[0] = 0x0161; -+ QTest::newRow("\u0161") << u << l << QString::fromUtf8("\u0161"); -+ } -+ { -+ const int l = 2; -+ Unicode *u = new Unicode[l]; -+ u[0] = int('a'); -+ u[1] = int('b'); -+ QTest::newRow("ab") << u << l << QString::fromUtf8("ab"); -+ } -+ { -+ const int l = 2; -+ Unicode *u = new Unicode[l]; -+ u[0] = int('a'); -+ u[1] = 0x0161; -+ QTest::newRow("a\u0161") << u << l << QString::fromUtf8("a\u0161"); -+ } -+ { -+ const int l = 2; -+ Unicode *u = new Unicode[l]; -+ u[0] = 0x5c01; -+ u[1] = 0x9762; -+ QTest::newRow("\xe5\xb0\x81\xe9\x9d\xa2") << u << l << QString::fromUtf8("\xe5\xb0\x81\xe9\x9d\xa2"); -+ } -+ { -+ const int l = 3; -+ Unicode *u = new Unicode[l]; -+ u[0] = 0x5c01; -+ u[1] = 0x9762; -+ u[2] = 0x0; -+ QTest::newRow("\xe5\xb0\x81\xe9\x9d\xa2 + 0") << u << l << QString::fromUtf8("\xe5\xb0\x81\xe9\x9d\xa2"); -+ } -+} -+ -+void TestStrings::check_unicodeToQString() -+{ -+ QFETCH(Unicode*, data); -+ QFETCH(int, length); -+ QFETCH(QString, result); -+ -+ QCOMPARE(Poppler::unicodeToQString(data, length), result); -+ -+ delete [] data; -+} -+ -+void TestStrings::check_UnicodeParsedString_data() -+{ -+ QTest::addColumn("string"); -+ QTest::addColumn("result"); -+ -+ // non-unicode strings -+ QTest::newRow("") << newGooString("") -+ << QString(); -+ QTest::newRow("a") << newGooString("a") -+ << QString::fromUtf8("a"); -+ QTest::newRow("ab") << newGooString("ab") -+ << QString::fromUtf8("ab"); -+ QTest::newRow("~") << newGooString("~") -+ << QString::fromUtf8("~"); -+ QTest::newRow("test string") << newGooString("test string") -+ << QString::fromUtf8("test string"); -+ -+ // unicode strings -+ QTest::newRow("") << newGooString("\xFE\xFF") -+ << QString(); -+ QTest::newRow("U a") << newGooString("\xFE\xFF\0a", 4) -+ << QString::fromUtf8("a"); -+ QTest::newRow("U ~") << newGooString("\xFE\xFF\0~", 4) -+ << QString::fromUtf8("~"); -+ QTest::newRow("U aa") << newGooString("\xFE\xFF\0a\0a", 6) -+ << QString::fromUtf8("aa"); -+ QTest::newRow("U \xC3\x9F") << newGooString("\xFE\xFF\0\xDF", 4) -+ << QString::fromUtf8("\xC3\x9F"); -+ QTest::newRow("U \xC3\x9F\x61") << newGooString("\xFE\xFF\0\xDF\0\x61", 6) -+ << QString::fromUtf8("\xC3\x9F\x61"); -+ QTest::newRow("U \xC5\xA1") << newGooString("\xFE\xFF\x01\x61", 4) -+ << QString::fromUtf8("\xC5\xA1"); -+ QTest::newRow("U \xC5\xA1\x61") << newGooString("\xFE\xFF\x01\x61\0\x61", 6) -+ << QString::fromUtf8("\xC5\xA1\x61"); -+ QTest::newRow("test string") << newGooString("\xFE\xFF\0t\0e\0s\0t\0 \0s\0t\0r\0i\0n\0g", 24) -+ << QString::fromUtf8("test string"); -+} -+ -+void TestStrings::check_UnicodeParsedString() -+{ -+ QFETCH(GooString*, string); -+ QFETCH(QString, result); -+ -+ QCOMPARE(Poppler::UnicodeParsedString(string), result); -+} -+ -+void TestStrings::check_QStringToUnicodeGooString_data() -+{ -+ QTest::addColumn("string"); -+ QTest::addColumn("result"); -+ -+ -+ QTest::newRow("") << QString() -+ << QByteArray(""); -+ QTest::newRow("") << QString::fromUtf8("") -+ << QByteArray(""); -+ QTest::newRow("a") << QString::fromUtf8("a") -+ << QByteArray("\0a", 2); -+ QTest::newRow("ab") << QString::fromUtf8("ab") -+ << QByteArray("\0a\0b", 4); -+ QTest::newRow("test string") << QString::fromUtf8("test string") -+ << QByteArray("\0t\0e\0s\0t\0 \0s\0t\0r\0i\0n\0g", 22); -+ QTest::newRow("\xC3\x9F") << QString::fromUtf8("\xC3\x9F") -+ << QByteArray("\0\xDF", 2); -+ QTest::newRow("\xC3\x9F\x61") << QString::fromUtf8("\xC3\x9F\x61") -+ << QByteArray("\0\xDF\0\x61", 4); -+} -+ -+void TestStrings::check_QStringToUnicodeGooString() -+{ -+ QFETCH(QString, string); -+ QFETCH(QByteArray, result); -+ -+ GooString *goo = Poppler::QStringToUnicodeGooString(string); -+ QVERIFY(goo->hasUnicodeMarker()); -+ QCOMPARE(goo->getLength(), string.length() * 2 + 2); -+ QCOMPARE(result, QByteArray::fromRawData(goo->c_str() + 2, goo->getLength() - 2)); -+ -+ delete goo; -+} -+ -+void TestStrings::check_QStringToGooString_data() -+{ -+ QTest::addColumn("string"); -+ QTest::addColumn("result"); -+ -+ QTest::newRow("") << QString() -+ << newGooString(""); -+ QTest::newRow("") << QString::fromUtf8("") -+ << newGooString(""); -+ QTest::newRow("a") << QString::fromUtf8("a") -+ << newGooString("a"); -+ QTest::newRow("ab") << QString::fromUtf8("ab") -+ << newGooString("ab"); -+} -+ -+void TestStrings::check_QStringToGooString() -+{ -+ QFETCH(QString, string); -+ QFETCH(GooString*, result); -+ -+ GooString *goo = Poppler::QStringToGooString(string); -+ QCOMPARE(goo->c_str(), result->c_str()); -+ -+ delete goo; -+} -+ -+GooString* TestStrings::newGooString(const char *s) -+{ -+ GooString *goo = new GooString(s); -+ m_gooStrings.append(goo); -+ return goo; -+} -+ -+GooString* TestStrings::newGooString(const char *s, int l) -+{ -+ GooString *goo = new GooString(s, l); -+ m_gooStrings.append(goo); -+ return goo; -+} -+ -+QTEST_MAIN(TestStrings) -+ -+#include "check_strings.moc" -diff --git a/qt4/tests/poppler-attachments.cpp b/qt4/tests/poppler-attachments.cpp -new file mode 100644 -index 00000000..992dc565 ---- /dev/null -+++ b/qt4/tests/poppler-attachments.cpp -@@ -0,0 +1,39 @@ -+#include -+#include -+ -+#include -+ -+#include -+ -+int main( int argc, char **argv ) -+{ -+ QCoreApplication a( argc, argv ); // QApplication required! -+ -+ if (!( argc == 2 )) -+ { -+ qWarning() << "usage: poppler-attachments filename"; -+ exit(1); -+ } -+ -+ Poppler::Document *doc = Poppler::Document::load(argv[1]); -+ if (!doc) -+ { -+ qWarning() << "doc not loaded"; -+ exit(1); -+ } -+ -+ if (doc->hasEmbeddedFiles()) { -+ std::cout << "Embedded files: " << std::endl; -+ foreach(Poppler::EmbeddedFile *file, doc->embeddedFiles()) { -+ std::cout << " " << qPrintable(file->name()) << std::endl; -+ std::cout << " desc:" << qPrintable(file->description()) << std::endl; -+ QByteArray data = file->data(); -+ std::cout << " data: " << data.constData() << std::endl; -+ } -+ -+ } else { -+ std::cout << "There are no embedded document at the top level" << std::endl; -+ } -+ delete doc; -+ -+} -diff --git a/qt4/tests/poppler-fonts.cpp b/qt4/tests/poppler-fonts.cpp -new file mode 100644 -index 00000000..6b66ec42 ---- /dev/null -+++ b/qt4/tests/poppler-fonts.cpp -@@ -0,0 +1,89 @@ -+#include -+#include -+ -+#include -+ -+#include -+ -+int main( int argc, char **argv ) -+{ -+ QCoreApplication a( argc, argv ); // QApplication required! -+ -+ if (!( argc == 2 )) -+ { -+ qWarning() << "usage: poppler-fonts filename"; -+ exit(1); -+ } -+ -+ Poppler::Document *doc = Poppler::Document::load(argv[1]); -+ if (!doc) -+ { -+ qWarning() << "doc not loaded"; -+ exit(1); -+ } -+ -+ std::cout << "name type emb sub font file"; -+ std::cout << std::endl; -+ std::cout << "------------------------------------ ------------ --- --- ---------"; -+ std::cout << std::endl; -+ -+ foreach( const Poppler::FontInfo &font, doc->fonts() ) { -+ if (font.name().isNull()) { -+ std::cout << qPrintable( QString("%1").arg(QString("[none]"), -37) ); -+ } else { -+ std::cout << qPrintable( QString("%1").arg(font.name(), -37) ); -+ } -+ switch( font.type() ) { -+ case Poppler::FontInfo::unknown: -+ std::cout << "unknown "; -+ break; -+ case Poppler::FontInfo::Type1: -+ std::cout << "Type 1 "; -+ break; -+ case Poppler::FontInfo::Type1C: -+ std::cout << "Type 1C "; -+ break; -+ case Poppler::FontInfo::Type3: -+ std::cout << "Type 3 "; -+ break; -+ case Poppler::FontInfo::TrueType: -+ std::cout << "TrueType "; -+ break; -+ case Poppler::FontInfo::CIDType0: -+ std::cout << "CID Type 0 "; -+ break; -+ case Poppler::FontInfo::CIDType0C: -+ std::cout << "CID Type 0C "; -+ break; -+ case Poppler::FontInfo::CIDTrueType: -+ std::cout << "CID TrueType "; -+ break; -+ case Poppler::FontInfo::Type1COT: -+ std::cout << "Type 1C (OT) "; -+ break; -+ case Poppler::FontInfo::TrueTypeOT: -+ std::cout << "TrueType (OT) "; -+ break; -+ case Poppler::FontInfo::CIDType0COT: -+ std::cout << "CID Type 0C (OT) "; -+ break; -+ case Poppler::FontInfo::CIDTrueTypeOT: -+ std::cout << "CID TrueType (OT) "; -+ break; -+ } -+ -+ if ( font.isEmbedded() ) { -+ std::cout << "yes "; -+ } else { -+ std::cout << "no "; -+ } -+ if ( font.isSubset() ) { -+ std::cout << "yes "; -+ } else { -+ std::cout << "no "; -+ } -+ std::cout << qPrintable( QString("%1").arg(font.file()) ); -+ std::cout << std::endl; -+ } -+ delete doc; -+} -diff --git a/qt4/tests/poppler-forms.cpp b/qt4/tests/poppler-forms.cpp -new file mode 100644 -index 00000000..98891a91 ---- /dev/null -+++ b/qt4/tests/poppler-forms.cpp -@@ -0,0 +1,166 @@ -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+static std::ostream& operator<< (std::ostream &out, Poppler::FormField::FormType type) -+{ -+ switch (type) { -+ case Poppler::FormField::FormButton: out << "Button"; break; -+ case Poppler::FormField::FormText: out << "Text"; break; -+ case Poppler::FormField::FormChoice: out << "Choice"; break; -+ case Poppler::FormField::FormSignature: out << "Signature"; break; -+ } -+ return out; -+} -+ -+static std::ostream& operator<< (std::ostream &out, Poppler::FormFieldButton::ButtonType type) -+{ -+ switch (type) { -+ case Poppler::FormFieldButton::Push: out << "Push"; break; -+ case Poppler::FormFieldButton::CheckBox: out << "CheckBox"; break; -+ case Poppler::FormFieldButton::Radio: out << "Radio"; break; -+ } -+ return out; -+} -+ -+static std::ostream& operator<< (std::ostream &out, Poppler::FormFieldText::TextType type) -+{ -+ switch (type) { -+ case Poppler::FormFieldText::Normal: out << "Normal"; break; -+ case Poppler::FormFieldText::Multiline: out << "Multiline"; break; -+ case Poppler::FormFieldText::FileSelect: out << "FileSelect"; break; -+ } -+ return out; -+} -+ -+static std::ostream& operator<< (std::ostream &out, Poppler::FormFieldChoice::ChoiceType type) -+{ -+ switch (type) { -+ case Poppler::FormFieldChoice::ComboBox: out << "ComboBox"; break; -+ case Poppler::FormFieldChoice::ListBox: out << "ListBox"; break; -+ } -+ return out; -+} -+ -+static std::ostream& operator<< (std::ostream &out, Qt::Alignment alignment) -+{ -+ switch (alignment) { -+ case Qt::AlignLeft: out << "Left"; break; -+ case Qt::AlignRight: out << "Right"; break; -+ case Qt::AlignHCenter: out << "HCenter"; break; -+ case Qt::AlignJustify: out << "Justify"; break; -+ case Qt::AlignTop: out << "Top"; break; -+ case Qt::AlignBottom: out << "Bottom"; break; -+ case Qt::AlignVCenter: out << "VCenter"; break; -+ case Qt::AlignCenter: out << "Center"; break; -+ case Qt::AlignAbsolute: out << "Absolute"; break; -+ } -+ return out; -+} -+ -+static std::ostream& operator<< (std::ostream &out, const QString &string) -+{ -+ out << string.toUtf8().constData(); -+ return out; -+} -+ -+static std::ostream& operator<< (std::ostream &out, const QRectF &rect) -+{ -+ out << QString("top: %1 left: %2 width: %3 height: %4").arg(rect.x()).arg(rect.y()).arg(rect.width()).arg(rect.height()); -+ return out; -+} -+ -+template -+std::ostream& operator<< (std::ostream &out, const QList &elems) -+{ -+ bool isFirst = true; -+ for (int i = 0; i < elems.count(); ++i) { -+ if (!isFirst) -+ out << " "; -+ out << elems[i]; -+ isFirst = false; -+ } -+ return out; -+} -+ -+int main( int argc, char **argv ) -+{ -+ QCoreApplication a( argc, argv ); -+ -+ if (!( argc == 2 )) -+ { -+ qWarning() << "usage: poppler-forms filename"; -+ exit(1); -+ } -+ -+ Poppler::Document *doc = Poppler::Document::load(argv[1]); -+ if (!doc) -+ { -+ qWarning() << "doc not loaded"; -+ exit(1); -+ } -+ -+ std::cout << "Forms for file " << argv[1] << std::endl; -+ for (int i = 0; i < doc->numPages(); ++i) { -+ Poppler::Page *page = doc->page(i); -+ if (page) { -+ QList forms = page->formFields(); -+ std::cout << "\tPage " << i + 1 << std::endl; -+ foreach( const Poppler::FormField *form, forms ) { -+ std::cout << "\t\tForm" << std::endl; -+ std::cout << "\t\t\tType: " << form->type() << std::endl; -+ std::cout << "\t\t\tRect: " << form->rect() << std::endl; -+ std::cout << "\t\t\tID: " << form->id() << std::endl; -+ std::cout << "\t\t\tName: " << form->name() << std::endl; -+ std::cout << "\t\t\tFullyQualifiedName: " << form->fullyQualifiedName() << std::endl; -+ std::cout << "\t\t\tUIName: " << form->uiName() << std::endl; -+ std::cout << "\t\t\tReadOnly: " << form->isReadOnly() << std::endl; -+ std::cout << "\t\t\tVisible: " << form->isVisible() << std::endl; -+ switch (form->type()) { -+ case Poppler::FormField::FormButton: { -+ const Poppler::FormFieldButton *buttonForm = static_cast(form); -+ std::cout << "\t\t\tButtonType: " << buttonForm->buttonType() << std::endl; -+ std::cout << "\t\t\tCaption: " << buttonForm->caption() << std::endl; -+ std::cout << "\t\t\tState: " << buttonForm->state() << std::endl; -+ std::cout << "\t\t\tSiblings: " << buttonForm->siblings() << std::endl; -+ } -+ break; -+ -+ case Poppler::FormField::FormText: { -+ const Poppler::FormFieldText *textForm = static_cast(form); -+ std::cout << "\t\t\tTextType: " << textForm->textType() << std::endl; -+ std::cout << "\t\t\tText: " << textForm->text() << std::endl; -+ std::cout << "\t\t\tIsPassword: " << textForm->isPassword() << std::endl; -+ std::cout << "\t\t\tIsRichText: " << textForm->isRichText() << std::endl; -+ std::cout << "\t\t\tMaximumLength: " << textForm->maximumLength() << std::endl; -+ std::cout << "\t\t\tTextAlignment: " << textForm->textAlignment() << std::endl; -+ std::cout << "\t\t\tCanBeSpellChecked: " << textForm->canBeSpellChecked() << std::endl; -+ } -+ break; -+ -+ case Poppler::FormField::FormChoice: { -+ const Poppler::FormFieldChoice *choiceForm = static_cast(form); -+ std::cout << "\t\t\tChoiceType: " << choiceForm->choiceType() << std::endl; -+ std::cout << "\t\t\tChoices: " << choiceForm->choices() << std::endl; -+ std::cout << "\t\t\tIsEditable: " << choiceForm->isEditable() << std::endl; -+ std::cout << "\t\t\tIsMultiSelect: " << choiceForm->multiSelect() << std::endl; -+ std::cout << "\t\t\tCurrentChoices: " << choiceForm->currentChoices() << std::endl; -+ std::cout << "\t\t\tEditChoice: " << choiceForm->editChoice() << std::endl; -+ std::cout << "\t\t\tTextAlignment: " << choiceForm->textAlignment() << std::endl; -+ std::cout << "\t\t\tCanBeSpellChecked: " << choiceForm->canBeSpellChecked() << std::endl; -+ } -+ break; -+ -+ case Poppler::FormField::FormSignature: -+ break; -+ } -+ } -+ qDeleteAll(forms); -+ } -+ } -+ delete doc; -+} -diff --git a/qt4/tests/poppler-texts.cpp b/qt4/tests/poppler-texts.cpp -new file mode 100644 -index 00000000..ec283531 ---- /dev/null -+++ b/qt4/tests/poppler-texts.cpp -@@ -0,0 +1,40 @@ -+#include -+#include -+ -+#include -+ -+#include -+ -+int main( int argc, char **argv ) -+{ -+ QCoreApplication a( argc, argv ); // QApplication required! -+ -+ if (!( argc == 2 )) -+ { -+ qWarning() << "usage: poppler-texts filename"; -+ exit(1); -+ } -+ -+ Poppler::Document *doc = Poppler::Document::load(argv[1]); -+ if (!doc) -+ { -+ qWarning() << "doc not loaded"; -+ exit(1); -+ } -+ -+ for ( int i = 0; i < doc->numPages(); i++ ) -+ { -+ int j = 0; -+ std::cout << "*** Page " << i << std::endl; -+ std::cout << std::flush; -+ -+ Poppler::Page *page = doc->page(i); -+ const QByteArray utf8str = page->text( QRectF(), Poppler::Page::RawOrderLayout ).toUtf8(); -+ std::cout << std::flush; -+ for ( j = 0; j < utf8str.size(); j++ ) -+ std::cout << utf8str[j]; -+ std::cout << std::endl; -+ delete page; -+ } -+ delete doc; -+} -diff --git a/qt4/tests/stress-poppler-dir.cpp b/qt4/tests/stress-poppler-dir.cpp -new file mode 100644 -index 00000000..6eeab6fa ---- /dev/null -+++ b/qt4/tests/stress-poppler-dir.cpp -@@ -0,0 +1,67 @@ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+ -+int main( int argc, char **argv ) -+{ -+ QApplication a( argc, argv ); // QApplication required! -+ -+ QTime t; -+ t.start(); -+ -+ QDir directory( argv[1] ); -+ foreach ( const QString &fileName, directory.entryList() ) { -+ if (fileName.endsWith("pdf") ) { -+ qDebug() << "Doing" << fileName.toLatin1().data() << ":"; -+ Poppler::Document *doc = Poppler::Document::load( directory.canonicalPath()+"/"+fileName ); -+ if (!doc) { -+ qWarning() << "doc not loaded"; -+ } else if ( doc->isLocked() ) { -+ if (! doc->unlock( "", "password" ) ) { -+ qWarning() << "couldn't unlock document"; -+ delete doc; -+ } -+ } else { -+ int major = 0, minor = 0; -+ doc->getPdfVersion( &major, &minor ); -+ doc->info("Title"); -+ doc->info("Subject"); -+ doc->info("Author"); -+ doc->info("Keywords"); -+ doc->info("Creator"); -+ doc->info("Producer"); -+ doc->date("CreationDate").toString(); -+ doc->date("ModDate").toString(); -+ doc->numPages(); -+ doc->isLinearized(); -+ doc->isEncrypted(); -+ doc->okToPrint(); -+ doc->okToCopy(); -+ doc->okToChange(); -+ doc->okToAddNotes(); -+ doc->pageMode(); -+ -+ for( int index = 0; index < doc->numPages(); ++index ) { -+ Poppler::Page *page = doc->page( index ); -+ QImage image = page->renderToImage(); -+ page->pageSize(); -+ page->orientation(); -+ delete page; -+ std::cout << "."; -+ std::cout.flush(); -+ } -+ std::cout << std::endl; -+ delete doc; -+ } -+ } -+ } -+ -+ std::cout << "Elapsed time: " << (t.elapsed()/1000) << "seconds" << std::endl; -+ -+} -diff --git a/qt4/tests/stress-poppler-qt4.cpp b/qt4/tests/stress-poppler-qt4.cpp -new file mode 100644 -index 00000000..56844543 ---- /dev/null -+++ b/qt4/tests/stress-poppler-qt4.cpp -@@ -0,0 +1,74 @@ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+ -+int main( int argc, char **argv ) -+{ -+ QApplication a( argc, argv ); // QApplication required! -+ -+ Q_UNUSED( argc ); -+ Q_UNUSED( argv ); -+ -+ QTime t; -+ t.start(); -+ QDir dbDir( QString( "./pdfdb" ) ); -+ if ( !dbDir.exists() ) { -+ qWarning() << "Database directory does not exist"; -+ } -+ -+ QStringList excludeSubDirs; -+ excludeSubDirs << "000048" << "000607"; -+ -+ foreach ( const QString &subdir, dbDir.entryList(QStringList() << "0000*", QDir::Dirs) ) { -+ if ( excludeSubDirs.contains(subdir) ) { -+ // then skip it -+ } else { -+ QString path = "./pdfdb/" + subdir + "/data.pdf"; -+ std::cout <<"Doing " << path.toLatin1().data() << " :"; -+ Poppler::Document *doc = Poppler::Document::load( path ); -+ if (!doc) { -+ qWarning() << "doc not loaded"; -+ } else { -+ int major = 0, minor = 0; -+ doc->getPdfVersion( &major, &minor ); -+ doc->info("Title"); -+ doc->info("Subject"); -+ doc->info("Author"); -+ doc->info("Keywords"); -+ doc->info("Creator"); -+ doc->info("Producer"); -+ doc->date("CreationDate").toString(); -+ doc->date("ModDate").toString(); -+ doc->numPages(); -+ doc->isLinearized(); -+ doc->isEncrypted(); -+ doc->okToPrint(); -+ doc->okToCopy(); -+ doc->okToChange(); -+ doc->okToAddNotes(); -+ doc->pageMode(); -+ -+ for( int index = 0; index < doc->numPages(); ++index ) { -+ Poppler::Page *page = doc->page( index ); -+ QImage image = page->renderToImage(); -+ page->pageSize(); -+ page->orientation(); -+ delete page; -+ std::cout << "."; -+ std::cout.flush(); -+ } -+ std::cout << std::endl; -+ delete doc; -+ } -+ } -+ } -+ -+ std::cout << "Elapsed time: " << (t.elapsed()/1000) << std::endl; -+ -+} -diff --git a/qt4/tests/stress-threads-qt4.cpp b/qt4/tests/stress-threads-qt4.cpp -new file mode 100644 -index 00000000..00968de1 ---- /dev/null -+++ b/qt4/tests/stress-threads-qt4.cpp -@@ -0,0 +1,309 @@ -+ -+#ifndef _WIN32 -+#include -+#else -+#include -+#define sleep Sleep -+#endif -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+class SillyThread : public QThread -+{ -+public: -+ SillyThread(Poppler::Document* document, QObject* parent = 0); -+ -+ void run(); -+ -+private: -+ Poppler::Document* m_document; -+ QVector< Poppler::Page* > m_pages; -+ -+}; -+ -+class CrazyThread : public QThread -+{ -+public: -+ CrazyThread(uint seed, Poppler::Document* document, QMutex* annotationMutex, QObject* parent = 0); -+ -+ void run(); -+ -+private: -+ uint m_seed; -+ Poppler::Document* m_document; -+ QMutex* m_annotationMutex; -+ -+}; -+ -+static Poppler::Page* loadPage(Poppler::Document* document, int index) -+{ -+ Poppler::Page* page = document->page(index); -+ -+ if(page == 0) -+ { -+ qDebug() << "!Document::page"; -+ -+ exit(EXIT_FAILURE); -+ } -+ -+ return page; -+} -+ -+static Poppler::Page* loadRandomPage(Poppler::Document* document) -+{ -+ return loadPage(document, qrand() % document->numPages()); -+} -+ -+SillyThread::SillyThread(Poppler::Document* document, QObject* parent) : QThread(parent), -+ m_document(document), -+ m_pages() -+{ -+ m_pages.reserve(m_document->numPages()); -+ -+ for(int index = 0; index < m_document->numPages(); ++index) -+ { -+ m_pages.append(loadPage(m_document, index)); -+ } -+} -+ -+ -+void SillyThread::run() -+{ -+ forever -+ { -+ foreach(Poppler::Page* page, m_pages) -+ { -+ QImage image = page->renderToImage(); -+ -+ if(image.isNull()) -+ { -+ qDebug() << "!Page::renderToImage"; -+ -+ ::exit(EXIT_FAILURE); -+ } -+ } -+ } -+} -+ -+CrazyThread::CrazyThread(uint seed, Poppler::Document* document, QMutex* annotationMutex, QObject* parent) : QThread(parent), -+ m_seed(seed), -+ m_document(document), -+ m_annotationMutex(annotationMutex) -+{ -+} -+ -+void CrazyThread::run() -+{ -+ typedef QScopedPointer< Poppler::Page > PagePointer; -+ -+ qsrand(m_seed); -+ -+ forever -+ { -+ if(qrand() % 2 == 0) -+ { -+ qDebug() << "search..."; -+ -+ PagePointer page(loadRandomPage(m_document)); -+ -+ page->search("c", Poppler::Page::CaseInsensitive); -+ page->search("r", Poppler::Page::CaseSensitive); -+ page->search("a", Poppler::Page::CaseInsensitive); -+ page->search("z", Poppler::Page::CaseSensitive); -+ page->search("y", Poppler::Page::CaseInsensitive); -+ } -+ -+ if(qrand() % 2 == 0) -+ { -+ qDebug() << "links..."; -+ -+ PagePointer page(loadRandomPage(m_document)); -+ -+ QList< Poppler::Link* > links = page->links(); -+ -+ qDeleteAll(links); -+ } -+ -+ if(qrand() % 2 == 0) -+ { -+ qDebug() << "form fields..."; -+ -+ PagePointer page(loadRandomPage(m_document)); -+ -+ QList< Poppler::FormField* > formFields = page->formFields(); -+ -+ qDeleteAll(formFields); -+ } -+ -+ if(qrand() % 2 == 0) -+ { -+ qDebug() << "thumbnail..."; -+ -+ PagePointer page(loadRandomPage(m_document)); -+ -+ page->thumbnail(); -+ } -+ -+ if(qrand() % 2 == 0) -+ { -+ qDebug() << "text..."; -+ -+ PagePointer page(loadRandomPage(m_document)); -+ -+ page->text(QRectF(QPointF(), page->pageSizeF())); -+ } -+ -+ if(qrand() % 2 == 0) -+ { -+ QMutexLocker mutexLocker(m_annotationMutex); -+ -+ qDebug() << "add annotation..."; -+ -+ PagePointer page(loadRandomPage(m_document)); -+ -+ Poppler::Annotation* annotation = 0; -+ -+ switch(qrand() % 3) -+ { -+ default: -+ case 0: -+ annotation = new Poppler::TextAnnotation(qrand() % 2 == 0 ? Poppler::TextAnnotation::Linked : Poppler::TextAnnotation::InPlace); -+ break; -+ case 1: -+ annotation = new Poppler::HighlightAnnotation(); -+ break; -+ case 2: -+ annotation = new Poppler::InkAnnotation(); -+ break; -+ } -+ -+ annotation->setBoundary(QRectF(0.0, 0.0, 0.5, 0.5)); -+ annotation->setContents("crazy"); -+ -+ page->addAnnotation(annotation); -+ -+ delete annotation; -+ } -+ -+ if(qrand() % 2 == 0) -+ { -+ QMutexLocker mutexLocker(m_annotationMutex); -+ -+ for(int index = 0; index < m_document->numPages(); ++index) -+ { -+ PagePointer page(loadPage(m_document, index)); -+ -+ QList< Poppler::Annotation* > annotations = page->annotations(); -+ -+ if(!annotations.isEmpty()) -+ { -+ qDebug() << "modify annotation..."; -+ -+ annotations.at(qrand() % annotations.size())->setBoundary(QRectF(0.5, 0.5, 0.25, 0.25)); -+ annotations.at(qrand() % annotations.size())->setAuthor("foo"); -+ annotations.at(qrand() % annotations.size())->setContents("bar"); -+ annotations.at(qrand() % annotations.size())->setCreationDate(QDateTime::currentDateTime()); -+ annotations.at(qrand() % annotations.size())->setModificationDate(QDateTime::currentDateTime()); -+ } -+ -+ qDeleteAll(annotations); -+ -+ if(!annotations.isEmpty()) -+ { -+ break; -+ } -+ } -+ } -+ -+ if(qrand() % 2 == 0) -+ { -+ QMutexLocker mutexLocker(m_annotationMutex); -+ -+ for(int index = 0; index < m_document->numPages(); ++index) -+ { -+ PagePointer page(loadPage(m_document, index)); -+ -+ QList< Poppler::Annotation* > annotations = page->annotations(); -+ -+ if(!annotations.isEmpty()) -+ { -+ qDebug() << "remove annotation..."; -+ -+ page->removeAnnotation(annotations.takeAt(qrand() % annotations.size())); -+ } -+ -+ qDeleteAll(annotations); -+ -+ if(!annotations.isEmpty()) -+ { -+ break; -+ } -+ } -+ } -+ -+ if(qrand() % 2 == 0) -+ { -+ qDebug() << "fonts..."; -+ -+ m_document->fonts(); -+ } -+ } -+} -+ -+int main(int argc, char** argv) -+{ -+ if(argc < 5) -+ { -+ qDebug() << "usage: stress-threads-qt duration sillyCount crazyCount file(s)"; -+ -+ return EXIT_FAILURE; -+ } -+ -+ const int duration = atoi(argv[1]); -+ const int sillyCount = atoi(argv[2]); -+ const int crazyCount = atoi(argv[3]); -+ -+ qsrand(time(0)); -+ -+ for(int argi = 4; argi < argc; ++argi) -+ { -+ const QString file = QFile::decodeName(argv[argi]); -+ Poppler::Document* document = Poppler::Document::load(file); -+ -+ if(document == 0) -+ { -+ qDebug() << "Could not load" << file; -+ continue; -+ } -+ -+ if(document->isLocked()) -+ { -+ qDebug() << file << "is locked"; -+ continue; -+ } -+ -+ for(int i = 0; i < sillyCount; ++i) -+ { -+ (new SillyThread(document))->start(); -+ } -+ -+ QMutex* annotationMutex = new QMutex(); -+ -+ for(int i = 0; i < crazyCount; ++i) -+ { -+ (new CrazyThread(qrand(), document, annotationMutex))->start(); -+ } -+ } -+ -+ sleep(duration); -+ -+ return EXIT_SUCCESS; -+} -diff --git a/qt4/tests/test-password-qt4.cpp b/qt4/tests/test-password-qt4.cpp -new file mode 100644 -index 00000000..c961874d ---- /dev/null -+++ b/qt4/tests/test-password-qt4.cpp -@@ -0,0 +1,136 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+class PDFDisplay : public QWidget // picture display widget -+{ -+public: -+ PDFDisplay( Poppler::Document *d ); -+ ~PDFDisplay(); -+protected: -+ void paintEvent( QPaintEvent * ); -+ void keyPressEvent( QKeyEvent * ); -+private: -+ void display(); -+ int m_currentPage; -+ QImage image; -+ Poppler::Document *doc; -+}; -+ -+PDFDisplay::PDFDisplay( Poppler::Document *d ) -+{ -+ doc = d; -+ m_currentPage = 0; -+ display(); -+} -+ -+void PDFDisplay::display() -+{ -+ if (doc) { -+ Poppler::Page *page = doc->page(m_currentPage); -+ if (page) { -+ qDebug() << "Displaying page: " << m_currentPage; -+ image = page->renderToImage(); -+ update(); -+ delete page; -+ } -+ } else { -+ qWarning() << "doc not loaded"; -+ } -+} -+ -+PDFDisplay::~PDFDisplay() -+{ -+ delete doc; -+} -+ -+void PDFDisplay::paintEvent( QPaintEvent *e ) -+{ -+ QPainter paint( this ); // paint widget -+ if (!image.isNull()) { -+ paint.drawImage(0, 0, image); -+ } else { -+ qWarning() << "null image"; -+ } -+} -+ -+void PDFDisplay::keyPressEvent( QKeyEvent *e ) -+{ -+ if (e->key() == Qt::Key_Down) -+ { -+ if (m_currentPage + 1 < doc->numPages()) -+ { -+ m_currentPage++; -+ display(); -+ } -+ } -+ else if (e->key() == Qt::Key_Up) -+ { -+ if (m_currentPage > 0) -+ { -+ m_currentPage--; -+ display(); -+ } -+ } -+ else if (e->key() == Qt::Key_Q) -+ { -+ exit(0); -+ } -+} -+ -+int main( int argc, char **argv ) -+{ -+ QApplication a( argc, argv ); // QApplication required! -+ -+ if ( argc != 3) -+ { -+ qWarning() << "usage: test-password-qt4 owner-password filename"; -+ exit(1); -+ } -+ -+ Poppler::Document *doc = Poppler::Document::load(argv[2], argv[1]); -+ if (!doc) -+ { -+ qWarning() << "doc not loaded"; -+ exit(1); -+ } -+ -+ // output some meta-data -+ int major = 0, minor = 0; -+ doc->getPdfVersion( &major, &minor ); -+ qDebug() << " PDF Version: " << qPrintable(QString::fromLatin1("%1.%2").arg(major).arg(minor)); -+ qDebug() << " Title: " << doc->info("Title"); -+ qDebug() << " Subject: " << doc->info("Subject"); -+ qDebug() << " Author: " << doc->info("Author"); -+ qDebug() << " Key words: " << doc->info("Keywords"); -+ qDebug() << " Creator: " << doc->info("Creator"); -+ qDebug() << " Producer: " << doc->info("Producer"); -+ qDebug() << " Date created: " << doc->date("CreationDate").toString(); -+ qDebug() << " Date modified: " << doc->date("ModDate").toString(); -+ qDebug() << "Number of pages: " << doc->numPages(); -+ qDebug() << " Linearised: " << doc->isLinearized(); -+ qDebug() << " Encrypted: " << doc->isEncrypted(); -+ qDebug() << " OK to print: " << doc->okToPrint(); -+ qDebug() << " OK to copy: " << doc->okToCopy(); -+ qDebug() << " OK to change: " << doc->okToChange(); -+ qDebug() << "OK to add notes: " << doc->okToAddNotes(); -+ qDebug() << " Page mode: " << doc->pageMode(); -+ QStringList fontNameList; -+ foreach( const Poppler::FontInfo &font, doc->fonts() ) -+ fontNameList += font.name(); -+ qDebug() << " Fonts: " << fontNameList.join( ", " ); -+ -+ Poppler::Page *page = doc->page(0); -+ qDebug() << " Page 1 size: " << page->pageSize().width()/72 << "inches x " << page->pageSize().height()/72 << "inches"; -+ -+ PDFDisplay test( doc ); // create picture display -+ test.setWindowTitle("Poppler-Qt4 Test"); -+ test.show(); // show it -+ -+ return a.exec(); // start event loop -+} -diff --git a/qt4/tests/test-poppler-qt4.cpp b/qt4/tests/test-poppler-qt4.cpp -new file mode 100644 -index 00000000..ae6b11f3 ---- /dev/null -+++ b/qt4/tests/test-poppler-qt4.cpp -@@ -0,0 +1,235 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+class PDFDisplay : public QWidget // picture display widget -+{ -+public: -+ PDFDisplay( Poppler::Document *d, bool arthur ); -+ ~PDFDisplay(); -+ void setShowTextRects(bool show); -+ void display(); -+protected: -+ void paintEvent( QPaintEvent * ); -+ void keyPressEvent( QKeyEvent * ); -+ void mousePressEvent( QMouseEvent * ); -+private: -+ int m_currentPage; -+ QImage image; -+ Poppler::Document *doc; -+ QString backendString; -+ bool showTextRects; -+ QList textRects; -+}; -+ -+PDFDisplay::PDFDisplay( Poppler::Document *d, bool arthur ) -+{ -+ showTextRects = false; -+ doc = d; -+ m_currentPage = 0; -+ if (arthur) -+ { -+ backendString = "Arthur"; -+ doc->setRenderBackend(Poppler::Document::ArthurBackend); -+ } -+ else -+ { -+ backendString = "Splash"; -+ doc->setRenderBackend(Poppler::Document::SplashBackend); -+ } -+ doc->setRenderHint(Poppler::Document::Antialiasing, true); -+ doc->setRenderHint(Poppler::Document::TextAntialiasing, true); -+} -+ -+void PDFDisplay::setShowTextRects(bool show) -+{ -+ showTextRects = show; -+} -+ -+void PDFDisplay::display() -+{ -+ if (doc) { -+ Poppler::Page *page = doc->page(m_currentPage); -+ if (page) { -+ qDebug() << "Displaying page using" << backendString << "backend: " << m_currentPage; -+ QTime t = QTime::currentTime(); -+ image = page->renderToImage(); -+ qDebug() << "Rendering took" << t.msecsTo(QTime::currentTime()) << "msecs"; -+ qDeleteAll(textRects); -+ if (showTextRects) -+ { -+ QPainter painter(&image); -+ painter.setPen(Qt::red); -+ textRects = page->textList(); -+ foreach(Poppler::TextBox *tb, textRects) -+ { -+ painter.drawRect(tb->boundingBox()); -+ } -+ } -+ else textRects.clear(); -+ update(); -+ delete page; -+ } -+ } else { -+ qWarning() << "doc not loaded"; -+ } -+} -+ -+PDFDisplay::~PDFDisplay() -+{ -+ qDeleteAll(textRects); -+ delete doc; -+} -+ -+void PDFDisplay::paintEvent( QPaintEvent *e ) -+{ -+ QPainter paint( this ); // paint widget -+ if (!image.isNull()) { -+ paint.drawImage(0, 0, image); -+ } else { -+ qWarning() << "null image"; -+ } -+} -+ -+void PDFDisplay::keyPressEvent( QKeyEvent *e ) -+{ -+ if (e->key() == Qt::Key_Down) -+ { -+ if (m_currentPage + 1 < doc->numPages()) -+ { -+ m_currentPage++; -+ display(); -+ } -+ } -+ else if (e->key() == Qt::Key_Up) -+ { -+ if (m_currentPage > 0) -+ { -+ m_currentPage--; -+ display(); -+ } -+ } -+ else if (e->key() == Qt::Key_Q) -+ { -+ exit(0); -+ } -+} -+ -+void PDFDisplay::mousePressEvent( QMouseEvent *e ) -+{ -+ int i = 0; -+ foreach(Poppler::TextBox *tb, textRects) -+ { -+ if (tb->boundingBox().contains(e->pos())) -+ { -+ QString tt = QString("Text: \"%1\"\nIndex in text list: %2").arg(tb->text()).arg(i); -+ QToolTip::showText(e->globalPos(), tt, this); -+ break; -+ } -+ ++i; -+ } -+} -+ -+int main( int argc, char **argv ) -+{ -+ QApplication a( argc, argv ); // QApplication required! -+ -+ if ( argc < 2 || -+ (argc == 3 && strcmp(argv[2], "-extract") != 0 && strcmp(argv[2], "-arthur") != 0 && strcmp(argv[2], "-textRects") != 0) || -+ argc > 3) -+ { -+ // use argument as file name -+ qWarning() << "usage: test-poppler-qt4 filename [-extract|-arthur|-textRects]"; -+ exit(1); -+ } -+ -+ Poppler::Document *doc = Poppler::Document::load(QFile::decodeName(argv[1])); -+ if (!doc) -+ { -+ qWarning() << "doc not loaded"; -+ exit(1); -+ } -+ -+ if (doc->isLocked()) -+ { -+ qWarning() << "document locked (needs password)"; -+ exit(0); -+ } -+ -+ // output some meta-data -+ int major = 0, minor = 0; -+ doc->getPdfVersion( &major, &minor ); -+ qDebug() << " PDF Version: " << qPrintable(QString::fromLatin1("%1.%2").arg(major).arg(minor)); -+ qDebug() << " Title: " << doc->info("Title"); -+ qDebug() << " Subject: " << doc->info("Subject"); -+ qDebug() << " Author: " << doc->info("Author"); -+ qDebug() << " Key words: " << doc->info("Keywords"); -+ qDebug() << " Creator: " << doc->info("Creator"); -+ qDebug() << " Producer: " << doc->info("Producer"); -+ qDebug() << " Date created: " << doc->date("CreationDate").toString(); -+ qDebug() << " Date modified: " << doc->date("ModDate").toString(); -+ qDebug() << "Number of pages: " << doc->numPages(); -+ qDebug() << " Linearised: " << doc->isLinearized(); -+ qDebug() << " Encrypted: " << doc->isEncrypted(); -+ qDebug() << " OK to print: " << doc->okToPrint(); -+ qDebug() << " OK to copy: " << doc->okToCopy(); -+ qDebug() << " OK to change: " << doc->okToChange(); -+ qDebug() << "OK to add notes: " << doc->okToAddNotes(); -+ qDebug() << " Page mode: " << doc->pageMode(); -+ qDebug() << " Metadata: " << doc->metadata(); -+ -+ if ( doc->hasEmbeddedFiles() ) { -+ qDebug() << "Embedded files:"; -+ foreach( Poppler::EmbeddedFile *file, doc->embeddedFiles() ) { -+ qDebug() << " " << file->name(); -+ } -+ qDebug(); -+ } else { -+ qDebug() << "No embedded files"; -+ } -+ -+ if (doc->numPages() <= 0) -+ { -+ delete doc; -+ qDebug() << "Doc has no pages"; -+ return 0; -+ } -+ -+ Poppler::Page *page = doc->page(0); -+ if (page) -+ { -+ qDebug() << "Page 1 size: " << page->pageSize().width()/72 << "inches x " << page->pageSize().height()/72 << "inches"; -+ delete page; -+ } -+ -+ if (argc == 2 || (argc == 3 && strcmp(argv[2], "-arthur") == 0) || (argc == 3 && strcmp(argv[2], "-textRects") == 0)) -+ { -+ bool useArthur = (argc == 3 && strcmp(argv[2], "-arthur") == 0); -+ PDFDisplay test( doc, useArthur ); // create picture display -+ test.setWindowTitle("Poppler-Qt4 Test"); -+ test.setShowTextRects(argc == 3 && strcmp(argv[2], "-textRects") == 0); -+ test.display(); -+ test.show(); // show it -+ -+ return a.exec(); // start event loop -+ } -+ else -+ { -+ Poppler::Page *page = doc->page(0); -+ -+ QLabel *l = new QLabel(page->text(QRectF()), 0); -+ l->show(); -+ delete page; -+ delete doc; -+ return a.exec(); -+ } -+} -diff --git a/qt4/tests/test-render-to-file.cpp b/qt4/tests/test-render-to-file.cpp -new file mode 100644 -index 00000000..b01aa03c ---- /dev/null -+++ b/qt4/tests/test-render-to-file.cpp -@@ -0,0 +1,69 @@ -+#include -+#include -+#include -+#include -+ -+#include -+ -+int main( int argc, char **argv ) -+{ -+ QApplication a( argc, argv ); // QApplication required! -+ -+ if ( argc < 2 || -+ (argc == 3 && strcmp(argv[2], "-arthur") != 0) || -+ argc > 3) -+ { -+ // use argument as file name -+ qWarning() << "usage: test-poppler-qt4 filename [-arthur]"; -+ exit(1); -+ } -+ -+ Poppler::Document *doc = Poppler::Document::load(QFile::decodeName(argv[1])); -+ if (!doc) -+ { -+ qWarning() << "doc not loaded"; -+ exit(1); -+ } -+ -+ if (doc->isLocked()) -+ { -+ qWarning() << "document locked (needs password)"; -+ exit(0); -+ } -+ -+ if (doc->numPages() <= 0) -+ { -+ delete doc; -+ qDebug() << "Doc has no pages"; -+ return 0; -+ } -+ -+ QString backendString; -+ if (argc == 3 && strcmp(argv[2], "-arthur") == 0) -+ { -+ backendString = "Arthur"; -+ doc->setRenderBackend(Poppler::Document::ArthurBackend); -+ } -+ else -+ { -+ backendString = "Splash"; -+ doc->setRenderBackend(Poppler::Document::SplashBackend); -+ } -+ doc->setRenderHint(Poppler::Document::Antialiasing, true); -+ doc->setRenderHint(Poppler::Document::TextAntialiasing, true); -+ -+ for (int i = 0; i < doc->numPages(); ++i) -+ { -+ Poppler::Page *page = doc->page(i); -+ if (page) { -+ qDebug() << "Rendering page using" << backendString << "backend: " << i; -+ QTime t = QTime::currentTime(); -+ QImage image = page->renderToImage(); -+ qDebug() << "Rendering took" << t.msecsTo(QTime::currentTime()) << "msecs"; -+ image.save(QString("test-rennder-to-file%1.ppm").arg(i)); -+ delete page; -+ } -+ } -+ -+ return 0; -+} --- -2.14.3 - diff --git a/poppler-0.30.0-rotated-words-selection.patch b/poppler-0.30.0-rotated-words-selection.patch index 33c6b8e..98230f9 100644 --- a/poppler-0.30.0-rotated-words-selection.patch +++ b/poppler-0.30.0-rotated-words-selection.patch @@ -17,8 +17,8 @@ index 7c2ca78..e93908c 100644 --- a/poppler/TextOutputDev.cc +++ b/poppler/TextOutputDev.cc @@ -178,6 +178,12 @@ - // (Or 1/tan(angle) for 90/270 degrees.) - #define diagonalThreshold 0.1 + // to read the underlying image. Issue #157 + #define glyphlessSelectionOpacity 0.4 +// Returns whether x is between a and b or equal to a or b. +// a and b don't need to be sorted. @@ -28,258 +28,252 @@ index 7c2ca78..e93908c 100644 + namespace { - inline bool isAscii7 (Unicode uchar) { + inline bool isAscii7(Unicode uchar) @@ -4411,11 +4417,37 @@ void TextSelectionSizer::visitLine (TextLine *line, - PDFRectangle *rect; - double x1, y1, x2, y2, margin; + PDFRectangle *rect; + double x1, y1, x2, y2, margin; -- margin = (line->yMax - line->yMin) / 8; -- x1 = line->edge[edge_begin]; -- y1 = line->yMin - margin; -- x2 = line->edge[edge_end]; -- y2 = line->yMax + margin; -+ switch (line->rot) { -+ default: -+ case 0: -+ margin = (line->yMax - line->yMin) / 8; -+ x1 = line->edge[edge_begin]; -+ x2 = line->edge[edge_end]; -+ y1 = line->yMin - margin; -+ y2 = line->yMax + margin; -+ break; -+ case 1: -+ margin = (line->xMax - line->xMin) / 8; -+ x1 = line->xMin - margin; -+ x2 = line->xMax + margin; -+ y1 = line->edge[edge_begin]; -+ y2 = line->edge[edge_end]; -+ break; -+ case 2: -+ margin = (line->yMax - line->yMin) / 8; -+ x1 = line->edge[edge_end]; -+ x2 = line->edge[edge_begin]; -+ y1 = line->yMin - margin; -+ y2 = line->yMax + margin; -+ break; -+ case 3: -+ margin = (line->xMax - line->xMin) / 8; -+ x1 = line->xMin - margin; -+ x2 = line->xMax + margin; -+ y1 = line->edge[edge_end]; -+ y2 = line->edge[edge_begin]; -+ break; -+ } +- margin = (line->yMax - line->yMin) / 8; +- x1 = line->edge[edge_begin]; +- y1 = line->yMin - margin; +- x2 = line->edge[edge_end]; +- y2 = line->yMax + margin; ++ switch (line->rot) { ++ default: ++ case 0: ++ margin = (line->yMax - line->yMin) / 8; ++ x1 = line->edge[edge_begin]; ++ x2 = line->edge[edge_end]; ++ y1 = line->yMin - margin; ++ y2 = line->yMax + margin; ++ break; ++ case 1: ++ margin = (line->xMax - line->xMin) / 8; ++ x1 = line->xMin - margin; ++ x2 = line->xMax + margin; ++ y1 = line->edge[edge_begin]; ++ y2 = line->edge[edge_end]; ++ break; ++ case 2: ++ margin = (line->yMax - line->yMin) / 8; ++ x1 = line->edge[edge_end]; ++ x2 = line->edge[edge_begin]; ++ y1 = line->yMin - margin; ++ y2 = line->yMax + margin; ++ break; ++ case 3: ++ margin = (line->xMax - line->xMin) / 8; ++ x1 = line->xMin - margin; ++ x2 = line->xMax + margin; ++ y1 = line->edge[edge_end]; ++ y2 = line->edge[edge_begin]; ++ break; ++ } - rect = new PDFRectangle (floor (x1 * scale), - floor (y1 * scale), + rect = new PDFRectangle(floor(x1 * scale), floor(y1 * scale), ceil(x2 * scale), ceil(y2 * scale)); + list->push_back(rect); @@ -4499,19 +4531,56 @@ void TextSelectionPainter::visitLine (TextLine *line, { - double x1, y1, x2, y2, margin; + double x1, y1, x2, y2, margin; -- margin = (line->yMax - line->yMin) / 8; -- x1 = floor (line->edge[edge_begin]); -- y1 = floor (line->yMin - margin); -- x2 = ceil (line->edge[edge_end]); -- y2 = ceil (line->yMax + margin); -+ switch (line->rot) { -+ default: -+ case 0: -+ margin = (line->yMax - line->yMin) / 8; -+ x1 = line->edge[edge_begin]; -+ x2 = line->edge[edge_end]; -+ y1 = line->yMin - margin; -+ y2 = line->yMax + margin; -+ break; -+ case 1: -+ margin = (line->xMax - line->xMin) / 8; -+ x1 = line->xMin - margin; -+ x2 = line->xMax + margin; -+ y1 = line->edge[edge_begin]; -+ y2 = line->edge[edge_end]; -+ break; -+ case 2: -+ margin = (line->yMax - line->yMin) / 8; -+ x1 = line->edge[edge_end]; -+ x2 = line->edge[edge_begin]; -+ y1 = line->yMin - margin; -+ y2 = line->yMax + margin; -+ break; -+ case 3: -+ margin = (line->xMax - line->xMin) / 8; -+ x1 = line->xMin - margin; -+ x2 = line->xMax + margin; -+ y1 = line->edge[edge_end]; -+ y2 = line->edge[edge_begin]; -+ break; -+ } -+ -+ ctm.transform(x1, y1, &x1, &y1); -+ ctm.transform(x2, y2, &x2, &y2); - -- ctm.transform(line->edge[edge_begin], line->yMin - margin, &x1, &y1); -- ctm.transform(line->edge[edge_end], line->yMax + margin, &x2, &y2); -+ if (x1 < x2) { -+ x1 = floor (x1); -+ x2 = ceil (x2); -+ } else { -+ x1 = ceil (x1); -+ x2 = floor (x2); -+ } - -- x1 = floor (x1); -- y1 = floor (y1); -- x2 = ceil (x2); -- y2 = ceil (y2); -+ if (y1 < y2) { -+ y1 = floor (y1); -+ y2 = ceil (y2); -+ } else { -+ y1 = ceil (y1); -+ y2 = floor (y2); -+ } - - ictm.transform(x1, y1, &x1, &y1); - ictm.transform(x2, y2, &x2, &y2); -@@ -4589,17 +4658,27 @@ void TextWord::visitSelection(TextSelectionVisitor *visitor, - SelectionStyle style) - { - int i, begin, end; -- double mid; -+ double mid, s1, s2; -+ -+ if (rot == 0 || rot == 2) { -+ s1 = selection->x1; -+ s2 = selection->x2; -+ } else { -+ s1 = selection->y1; -+ s2 = selection->y2; -+ } - - begin = len; - end = 0; - for (i = 0; i < len; i++) { - mid = (edge[i] + edge[i + 1]) / 2; -- if (selection->x1 < mid || selection->x2 < mid) -- if (i < begin) -- begin = i; -- if (mid < selection->x1 || mid < selection->x2) -- end = i + 1; -+ if (XBetweenAB (mid, s1, s2)) -+ { -+ if (i < begin) -+ begin = i; -+ -+ end = i + 1; -+ } - } - - /* Skip empty selection. */ -@@ -4615,30 +4694,41 @@ void TextLine::visitSelection(TextSelectionVisitor *visitor, - TextWord *p, *begin, *end, *current; - int i, edge_begin, edge_end; - PDFRectangle child_selection; -+ double s1, s2, p_min, p_max; -+ -+ if (rot == 0 || rot == 2) { -+ s1 = selection->x1; -+ s2 = selection->x2; -+ } else { -+ s1 = selection->y1; -+ s2 = selection->y2; -+ } - - begin = nullptr; - end = nullptr; - current = nullptr; - for (p = words; p != nullptr; p = p->next) { -+ if (rot == 0 || rot == 2) { -+ p_min = p->xMin; -+ p_max = p->xMax; -+ } else { -+ p_min = p->yMin; -+ p_max = p->yMax; +- margin = (line->yMax - line->yMin) / 8; +- x1 = floor(line->edge[edge_begin]); +- y1 = floor(line->yMin - margin); +- x2 = ceil(line->edge[edge_end]); +- y2 = ceil(line->yMax + margin); ++ switch (line->rot) { ++ default: ++ case 0: ++ margin = (line->yMax - line->yMin) / 8; ++ x1 = line->edge[edge_begin]; ++ x2 = line->edge[edge_end]; ++ y1 = line->yMin - margin; ++ y2 = line->yMax + margin; ++ break; ++ case 1: ++ margin = (line->xMax - line->xMin) / 8; ++ x1 = line->xMin - margin; ++ x2 = line->xMax + margin; ++ y1 = line->edge[edge_begin]; ++ y2 = line->edge[edge_end]; ++ break; ++ case 2: ++ margin = (line->yMax - line->yMin) / 8; ++ x1 = line->edge[edge_end]; ++ x2 = line->edge[edge_begin]; ++ y1 = line->yMin - margin; ++ y2 = line->yMax + margin; ++ break; ++ case 3: ++ margin = (line->xMax - line->xMin) / 8; ++ x1 = line->xMin - margin; ++ x2 = line->xMax + margin; ++ y1 = line->edge[edge_end]; ++ y2 = line->edge[edge_begin]; ++ break; + } + - if (blk->page->primaryLR) { -- if ((selection->x1 < p->xMax) || -- (selection->x2 < p->xMax)) -- if (begin == nullptr) -- begin = p; -+ if (((s1 < p_max) || (s2 < p_max)) && begin == nullptr) -+ begin = p; ++ ctm.transform(x1, y1, &x1, &y1); ++ ctm.transform(x2, y2, &x2, &y2); -- if (((selection->x1 > p->xMin) || -- (selection->x2 > p->xMin)) && (begin != nullptr)) { -+ if (((s1 > p_min) || (s2 > p_min)) && begin != nullptr) { - end = p->next; - current = p; - } - } else { -- if ((selection->x1 > p->xMin) || -- (selection->x2 > p->xMin)) -- if (begin == nullptr) -- begin = p; -+ if (((s1 > p_min) || (s2 > p_min)) && begin == nullptr) -+ begin = p; +- ctm.transform(line->edge[edge_begin], line->yMin - margin, &x1, &y1); +- ctm.transform(line->edge[edge_end], line->yMax + margin, &x2, &y2); ++ if (x1 < x2) { ++ x1 = floor(x1); ++ x2 = ceil(x2); ++ } else { ++ x1 = ceil(x1); ++ x2 = floor(x2); ++ } -- if (((selection->x1 < p->xMax) || -- (selection->x2 < p->xMax)) && (begin != nullptr)) { -+ if (((s1 < p_max) || (s2 < p_max)) && begin != nullptr) { - end = p->next; - current = p; - } -@@ -4650,23 +4740,42 @@ void TextLine::visitSelection(TextSelectionVisitor *visitor, - - child_selection = *selection; - if (style == selectionStyleWord) { -- child_selection.x1 = begin ? begin->xMin : xMin; -- if (end && end->xMax != -1) { -- child_selection.x2 = current->xMax; +- x1 = floor(x1); +- y1 = floor(y1); +- x2 = ceil(x2); +- y2 = ceil(y2); ++ if (y1 < y2) { ++ y1 = floor(y1); ++ y2 = ceil(y2); ++ } else { ++ y1 = ceil(y1); ++ y2 = floor(y2); ++ } + + ictm.transform(x1, y1, &x1, &y1); + ictm.transform(x2, y2, &x2, &y2); +@@ -4589,17 +4658,26 @@ void TextWord::visitSelection(TextSelectionVisitor *visitor, + void TextWord::visitSelection(TextSelectionVisitor *visitor, const PDFRectangle *selection, SelectionStyle style) + { + int i, begin, end; +- double mid; ++ double mid, s1, s2; ++ + if (rot == 0 || rot == 2) { -+ child_selection.x1 = begin ? begin->xMin : xMin; -+ if (end && end->xMax != -1) { -+ child_selection.x2 = current->xMax; -+ } else { -+ child_selection.x2 = xMax; -+ } - } else { -- child_selection.x2 = xMax; -+ child_selection.y1 = begin ? begin->yMin : yMin; -+ if (end && end->yMax != -1) { -+ child_selection.y2 = current->yMax; -+ } else { -+ child_selection.y2 = yMax; ++ s1 = selection->x1; ++ s2 = selection->x2; ++ } else { ++ s1 = selection->y1; ++ s2 = selection->y2; ++ } + + begin = len; + end = 0; + for (i = 0; i < len; i++) { + mid = (edge[i] + edge[i + 1]) / 2; +- if (selection->x1 < mid || selection->x2 < mid) +- if (i < begin) +- begin = i; +- if (mid < selection->x1 || mid < selection->x2) +- end = i + 1; ++ if (XBetweenAB (mid, s1, s2)) { ++ if (i < begin) ++ begin = i; ++ ++ end = i + 1; + } } - } -+ if (rot == 0 || rot == 2) { -+ s1 = child_selection.x1; -+ s2 = child_selection.x2; -+ } else { -+ s1 = child_selection.y1; -+ s2 = child_selection.y2; -+ } + /* Skip empty selection. */ +@@ -4615,26 +4694,41 @@ void TextLine::visitSelection(TextSelectionVisitor *visitor, + TextWord *p, *begin, *end, *current; + int i, edge_begin, edge_end; + PDFRectangle child_selection; ++ double s1, s2, p_min, p_max; + - edge_begin = len; - edge_end = 0; - for (i = 0; i < len; i++) { - double mid = (edge[i] + edge[i + 1]) / 2; -- if (child_selection.x1 < mid || child_selection.x2 < mid) -- if (i < edge_begin) -- edge_begin = i; -- if (mid < child_selection.x2 || mid < child_selection.x1) -- edge_end = i + 1; -+ if (XBetweenAB (mid, s1, s2)) -+ { -+ if (i < edge_begin) -+ edge_begin = i; -+ -+ edge_end = i + 1; -+ } - } ++ if (rot == 0 || rot == 2) { ++ s1 = selection->x1; ++ s2 = selection->x2; ++ } else { ++ s1 = selection->y1; ++ s2 = selection->y2; ++ } - /* Skip empty selection. */ + begin = nullptr; + end = nullptr; + current = nullptr; + for (p = words; p != nullptr; p = p->next) { ++ if (rot == 0 || rot == 2) { ++ p_min = p->xMin; ++ p_max = p->xMax; ++ } else { ++ p_min = p->yMin; ++ p_max = p->yMax; ++ } ++ + if (blk->page->primaryLR) { +- if ((selection->x1 < p->xMax) || (selection->x2 < p->xMax)) +- if (begin == nullptr) +- begin = p; ++ if (((s1 < p_max) || (s2 < p_max)) && begin == nullptr) ++ begin = p; + +- if (((selection->x1 > p->xMin) || (selection->x2 > p->xMin)) && (begin != nullptr)) { ++ if (((s1 > p_min) || (s2 > p_min)) && begin != nullptr) { + end = p->next; + current = p; + } + } else { +- if ((selection->x1 > p->xMin) || (selection->x2 > p->xMin)) +- if (begin == nullptr) +- begin = p; ++ if (((s1 > p_min) || (s2 > p_min)) && begin == nullptr) ++ begin = p; + +- if (((selection->x1 < p->xMax) || (selection->x2 < p->xMax)) && (begin != nullptr)) { ++ if (((s1 < p_max) || (s2 < p_max)) && begin != nullptr) { + end = p->next; + current = p; + } +@@ -4650,23 +4740,41 @@ void TextLine::visitSelection(TextSelectionVisitor *visitor, + + child_selection = *selection; + if (style == selectionStyleWord) { +- child_selection.x1 = begin ? begin->xMin : xMin; +- if (end && end->xMax != -1) { +- child_selection.x2 = current->xMax; ++ if (rot == 0 || rot == 2) { ++ child_selection.x1 = begin ? begin->xMin : xMin; ++ if (end && end->xMax != -1) { ++ child_selection.x2 = current->xMax; ++ } else { ++ child_selection.x2 = xMax; ++ } + } else { +- child_selection.x2 = xMax; ++ child_selection.y1 = begin ? begin->yMin : yMin; ++ if (end && end->yMax != -1) { ++ child_selection.y2 = current->yMax; ++ } else { ++ child_selection.y2 = yMax; ++ } + } + } + ++ if (rot == 0 || rot == 2) { ++ s1 = child_selection.x1; ++ s2 = child_selection.x2; ++ } else { ++ s1 = child_selection.y1; ++ s2 = child_selection.y2; ++ } ++ + edge_begin = len; + edge_end = 0; + for (i = 0; i < len; i++) { + double mid = (edge[i] + edge[i + 1]) / 2; +- if (child_selection.x1 < mid || child_selection.x2 < mid) +- if (i < edge_begin) +- edge_begin = i; +- if (mid < child_selection.x2 || mid < child_selection.x1) +- edge_end = i + 1; ++ if (XBetweenAB (mid, s1, s2)) { ++ if (i < edge_begin) ++ edge_begin = i; ++ ++ edge_end = i + 1; ++ } + } + + /* Skip empty selection. */ -- 1.8.4.2 diff --git a/poppler-0.67.0-qt4-const.patch b/poppler-0.67.0-qt4-const.patch deleted file mode 100644 index 109eb83..0000000 --- a/poppler-0.67.0-qt4-const.patch +++ /dev/null @@ -1,150 +0,0 @@ ---- poppler-0.67.0/qt4/src/poppler-document.cc.orig 2018-08-08 10:13:17.130028069 +0200 -+++ poppler-0.67.0/qt4/src/poppler-document.cc 2018-08-08 11:14:58.301690615 +0200 -@@ -799,7 +799,7 @@ namespace Poppler { - return Document::NoForm; // make gcc happy - } - -- QDateTime convertDate( char *dateString ) -+ QDateTime convertDate( const char *dateString ) - { - int year, mon, day, hour, min, sec, tzHours, tzMins; - char tz; -@@ -830,6 +830,12 @@ namespace Poppler { - return QDateTime(); - } - -+ QDateTime convertDate( char *dateString ) -+ { -+ return convertDate( (const char *) dateString ); -+ } -+ -+ - bool isCmsAvailable() - { - #if defined(USE_CMS) ---- poppler-0.67.0/qt4/src/poppler-embeddedfile.cc.orig 2018-08-08 10:13:17.130028069 +0200 -+++ poppler-0.67.0/qt4/src/poppler-embeddedfile.cc 2018-08-08 10:50:42.645723179 +0200 -@@ -68,13 +68,13 @@ EmbeddedFile::~EmbeddedFile() - - QString EmbeddedFile::name() const - { -- GooString *goo = m_embeddedFile->filespec->getFileName(); -+ const GooString *goo = m_embeddedFile->filespec->getFileName(); - return goo ? UnicodeParsedString(goo) : QString(); - } - - QString EmbeddedFile::description() const - { -- GooString *goo = m_embeddedFile->filespec->getDescription(); -+ const GooString *goo = m_embeddedFile->filespec->getDescription(); - return goo ? UnicodeParsedString(goo) : QString(); - } - -@@ -85,25 +85,25 @@ int EmbeddedFile::size() const - - QDateTime EmbeddedFile::modDate() const - { -- GooString *goo = m_embeddedFile->embFile() ? m_embeddedFile->embFile()->modDate() : NULL; -+ const GooString *goo = m_embeddedFile->embFile() ? m_embeddedFile->embFile()->modDate() : NULL; - return goo ? convertDate(goo->c_str()) : QDateTime(); - } - - QDateTime EmbeddedFile::createDate() const - { -- GooString *goo = m_embeddedFile->embFile() ? m_embeddedFile->embFile()->createDate() : NULL; -+ const GooString *goo = m_embeddedFile->embFile() ? m_embeddedFile->embFile()->createDate() : NULL; - return goo ? convertDate(goo->c_str()) : QDateTime(); - } - - QByteArray EmbeddedFile::checksum() const - { -- GooString *goo = m_embeddedFile->embFile() ? m_embeddedFile->embFile()->checksum() : NULL; -+ const GooString *goo = m_embeddedFile->embFile() ? m_embeddedFile->embFile()->checksum() : NULL; - return goo ? QByteArray::fromRawData(goo->c_str(), goo->getLength()) : QByteArray(); - } - - QString EmbeddedFile::mimeType() const - { -- GooString *goo = m_embeddedFile->embFile() ? m_embeddedFile->embFile()->mimeType() : NULL; -+ const GooString *goo = m_embeddedFile->embFile() ? m_embeddedFile->embFile()->mimeType() : NULL; - return goo ? QString(goo->c_str()) : QString(); - } - ---- poppler-0.67.0/qt4/src/poppler-movie.cc.orig 2018-08-08 10:13:17.131028077 +0200 -+++ poppler-0.67.0/qt4/src/poppler-movie.cc 2018-08-08 10:52:41.284914743 +0200 -@@ -57,7 +57,7 @@ MovieObject::MovieObject( AnnotMovie *an - m_movieData->m_movieObj = ann->getMovie()->copy(); - //TODO: copy poster image - -- MovieActivationParameters *mp = m_movieData->m_movieObj->getActivationParameters(); -+ const MovieActivationParameters *mp = m_movieData->m_movieObj->getActivationParameters(); - int width, height; - m_movieData->m_movieObj->getFloatingWindowSize(&width, &height); - m_movieData->m_size = QSize(width, height); -@@ -73,7 +73,7 @@ MovieObject::~MovieObject() - - QString MovieObject::url() const - { -- GooString * goo = m_movieData->m_movieObj->getFileName(); -+ const GooString * goo = m_movieData->m_movieObj->getFileName(); - return goo ? QString( goo->c_str() ) : QString(); - } - ---- poppler-0.67.0/qt4/src/poppler-private.h.orig 2018-08-08 10:13:17.132028085 +0200 -+++ poppler-0.67.0/qt4/src/poppler-private.h 2018-08-08 11:00:30.836672893 +0200 -@@ -54,9 +54,9 @@ class FormWidget; - namespace Poppler { - - /* borrowed from kpdf */ -- QString unicodeToQString(Unicode* u, int len); -+ QString unicodeToQString(const Unicode* u, int len); - -- QString UnicodeParsedString(GooString *s1); -+ QString UnicodeParsedString(const GooString *s1); - - GooString *QStringToUnicodeGooString(const QString &s); - -@@ -69,13 +69,13 @@ namespace Poppler { - class LinkDestinationData - { - public: -- LinkDestinationData( LinkDest *l, GooString *nd, Poppler::DocumentData *pdfdoc, bool external ) -+ LinkDestinationData( const LinkDest *l, const GooString *nd, Poppler::DocumentData *pdfdoc, bool external ) - : ld(l), namedDest(nd), doc(pdfdoc), externalDest(external) - { - } - -- LinkDest *ld; -- GooString *namedDest; -+ const LinkDest *ld; -+ const GooString *namedDest; - Poppler::DocumentData *doc; - bool externalDest; - }; ---- poppler-0.67.0/qt4/src/poppler-qt4.h.orig 2018-08-08 10:13:17.133028093 +0200 -+++ poppler-0.67.0/qt4/src/poppler-qt4.h 2018-08-08 10:29:23.807858790 +0200 -@@ -1816,7 +1816,12 @@ height = dummy.height(); - /** - Conversion from PDF date string format to QDateTime - */ -- POPPLER_QT4_EXPORT QDateTime convertDate( char *dateString ); -+ POPPLER_QT4_EXPORT Q_DECL_DEPRECATED QDateTime convertDate( char *dateString ); -+ -+ /** -+ Conversion from PDF date string format to QDateTime -+ */ -+ POPPLER_QT4_EXPORT QDateTime convertDate( const char *dateString ); - - /** - Whether the color management functions are available. ---- poppler-0.67.0/qt4/src/poppler-sound.cc.orig 2018-08-08 10:13:17.133028093 +0200 -+++ poppler-0.67.0/qt4/src/poppler-sound.cc 2018-08-08 11:10:31.644004477 +0200 -@@ -75,7 +75,7 @@ QString SoundObject::url() const - if ( m_soundData->m_type != SoundObject::External ) - return QString(); - -- GooString * goo = m_soundData->m_soundObj->getFileName(); -+ const GooString * goo = m_soundData->m_soundObj->getFileName(); - return goo ? QString( goo->c_str() ) : QString(); - } - diff --git a/poppler-0.73.0-PSOutputDev-buffer-read.patch b/poppler-0.73.0-PSOutputDev-buffer-read.patch deleted file mode 100644 index 707ef1b..0000000 --- a/poppler-0.73.0-PSOutputDev-buffer-read.patch +++ /dev/null @@ -1,289 +0,0 @@ -From 9bcc9d0a164dbd1f24aae8f900c28feafd0cb3f2 Mon Sep 17 00:00:00 2001 -From: Marek Kasik -Date: Tue, 30 Apr 2019 18:47:44 +0200 -Subject: [PATCH] PSOutputDev: Don't read outside of image buffer - -Check whether input image is RGB or BGR to not treat -it as CMYK in those cases in PSOutputDev::checkPageSlice(). - -Fixes #751 ---- - poppler/PSOutputDev.cc | 248 ++++++++++++++++++++++++++++++++--------- - 1 file changed, 196 insertions(+), 52 deletions(-) - -diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc -index 0d201835..155a8cbe 100644 ---- a/poppler/PSOutputDev.cc -+++ b/poppler/PSOutputDev.cc -@@ -3374,6 +3374,14 @@ bool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/, - } - break; - case psLevel1Sep: -+ GfxColor inputColor; -+ GfxCMYK cmyk; -+ unsigned char cmykColor[4]; -+ GfxDeviceRGBColorSpace *rgbCS; -+ SplashColorMode colorMode; -+ -+ colorMode = bitmap->getMode(); -+ - p = bitmap->getDataPtr(); - // Check for an all gray image - if (getOptimizeColorSpace()) { -@@ -3448,65 +3456,201 @@ bool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/, - } - } else if (((psProcessCyan | psProcessMagenta | psProcessYellow | psProcessBlack) & ~processColors) != 0) { - // Color image, need to check color flags for each dot -- for (y = 0; y < h; ++y) { -- for (comp = 0; comp < 4; ++comp) { -- if (useBinary) { -- // Binary color image -- for (x = 0; x < w; ++x) { -- col[comp] |= p[4*x + comp]; -- hexBuf[i++] = p[4*x + comp]; -- if (i >= 64) { -- writePSBuf(hexBuf, i); -- i = 0; -+ switch (colorMode) { -+ case splashModeRGB8: -+ case splashModeBGR8: -+ rgbCS = new GfxDeviceRGBColorSpace(); -+ for (y = 0; y < h; ++y) { -+ for (comp = 0; comp < 4; ++comp) { -+ if (useBinary) { -+ // Binary color image -+ for (x = 0; x < w; ++x) { -+ if (likely(colorMode == splashModeRGB8)) { -+ inputColor.c[0] = byteToCol(p[3*x + 0]); -+ inputColor.c[1] = byteToCol(p[3*x + 1]); -+ inputColor.c[2] = byteToCol(p[3*x + 2]); -+ } else { -+ inputColor.c[0] = byteToCol(p[3*x + 2]); -+ inputColor.c[1] = byteToCol(p[3*x + 1]); -+ inputColor.c[2] = byteToCol(p[3*x + 0]); -+ } -+ rgbCS->getCMYK(&inputColor, &cmyk); -+ cmykColor[0] = colToByte(cmyk.c); -+ cmykColor[1] = colToByte(cmyk.m); -+ cmykColor[2] = colToByte(cmyk.y); -+ cmykColor[3] = colToByte(cmyk.k); -+ -+ col[comp] |= cmykColor[comp]; -+ hexBuf[i++] = cmykColor[comp]; -+ if (i >= 64) { -+ writePSBuf(hexBuf, i); -+ i = 0; -+ } -+ } -+ } else { -+ // Gray color image -+ for (x = 0; x < w; ++x) { -+ if (likely(colorMode == splashModeRGB8)) { -+ inputColor.c[0] = byteToCol(p[3*x + 0]); -+ inputColor.c[1] = byteToCol(p[3*x + 1]); -+ inputColor.c[2] = byteToCol(p[3*x + 2]); -+ } else { -+ inputColor.c[0] = byteToCol(p[3*x + 2]); -+ inputColor.c[1] = byteToCol(p[3*x + 1]); -+ inputColor.c[2] = byteToCol(p[3*x + 0]); -+ } -+ rgbCS->getCMYK(&inputColor, &cmyk); -+ cmykColor[0] = colToByte(cmyk.c); -+ cmykColor[1] = colToByte(cmyk.m); -+ cmykColor[2] = colToByte(cmyk.y); -+ cmykColor[3] = colToByte(cmyk.k); -+ -+ col[comp] |= cmykColor[comp]; -+ digit = cmykColor[comp] / 16; -+ hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); -+ digit = cmykColor[comp] % 16; -+ hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); -+ if (i >= 64) { -+ hexBuf[i++] = '\n'; -+ writePSBuf(hexBuf, i); -+ i = 0; -+ } -+ } - } -- } -- } else { -- // Gray color image -- for (x = 0; x < w; ++x) { -- col[comp] |= p[4*x + comp]; -- digit = p[4*x + comp] / 16; -- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); -- digit = p[4*x + comp] % 16; -- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); -- if (i >= 64) { -- hexBuf[i++] = '\n'; -- writePSBuf(hexBuf, i); -- i = 0; -+ } -+ p -= bitmap->getRowSize(); -+ } -+ delete rgbCS; -+ break; -+ default: -+ for (y = 0; y < h; ++y) { -+ for (comp = 0; comp < 4; ++comp) { -+ if (useBinary) { -+ // Binary color image -+ for (x = 0; x < w; ++x) { -+ col[comp] |= p[4*x + comp]; -+ hexBuf[i++] = p[4*x + comp]; -+ if (i >= 64) { -+ writePSBuf(hexBuf, i); -+ i = 0; -+ } -+ } -+ } else { -+ // Gray color image -+ for (x = 0; x < w; ++x) { -+ col[comp] |= p[4*x + comp]; -+ digit = p[4*x + comp] / 16; -+ hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); -+ digit = p[4*x + comp] % 16; -+ hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); -+ if (i >= 64) { -+ hexBuf[i++] = '\n'; -+ writePSBuf(hexBuf, i); -+ i = 0; -+ } -+ } - } -- } -- } -- } -- p -= bitmap->getRowSize(); -+ } -+ p -= bitmap->getRowSize(); -+ } -+ break; - } - } else { - // Color image, do not need to check color flags -- for (y = 0; y < h; ++y) { -- for (comp = 0; comp < 4; ++comp) { -- if (useBinary) { -- // Binary color image -- for (x = 0; x < w; ++x) { -- hexBuf[i++] = p[4*x + comp]; -- if (i >= 64) { -- writePSBuf(hexBuf, i); -- i = 0; -+ switch (colorMode) { -+ case splashModeRGB8: -+ case splashModeBGR8: -+ rgbCS = new GfxDeviceRGBColorSpace(); -+ for (y = 0; y < h; ++y) { -+ for (comp = 0; comp < 4; ++comp) { -+ if (useBinary) { -+ // Binary color image -+ for (x = 0; x < w; ++x) { -+ if (likely(colorMode == splashModeRGB8)) { -+ inputColor.c[0] = byteToCol(p[3*x + 0]); -+ inputColor.c[1] = byteToCol(p[3*x + 1]); -+ inputColor.c[2] = byteToCol(p[3*x + 2]); -+ } else { -+ inputColor.c[0] = byteToCol(p[3*x + 2]); -+ inputColor.c[1] = byteToCol(p[3*x + 1]); -+ inputColor.c[2] = byteToCol(p[3*x + 0]); -+ } -+ rgbCS->getCMYK(&inputColor, &cmyk); -+ cmykColor[0] = colToByte(cmyk.c); -+ cmykColor[1] = colToByte(cmyk.m); -+ cmykColor[2] = colToByte(cmyk.y); -+ cmykColor[3] = colToByte(cmyk.k); -+ -+ hexBuf[i++] = cmykColor[comp]; -+ if (i >= 64) { -+ writePSBuf(hexBuf, i); -+ i = 0; -+ } -+ } -+ } else { -+ // Hex color image -+ for (x = 0; x < w; ++x) { -+ if (likely(colorMode == splashModeRGB8)) { -+ inputColor.c[0] = byteToCol(p[3*x + 0]); -+ inputColor.c[1] = byteToCol(p[3*x + 1]); -+ inputColor.c[2] = byteToCol(p[3*x + 2]); -+ } else { -+ inputColor.c[0] = byteToCol(p[3*x + 2]); -+ inputColor.c[1] = byteToCol(p[3*x + 1]); -+ inputColor.c[2] = byteToCol(p[3*x + 0]); -+ } -+ rgbCS->getCMYK(&inputColor, &cmyk); -+ cmykColor[0] = colToByte(cmyk.c); -+ cmykColor[1] = colToByte(cmyk.m); -+ cmykColor[2] = colToByte(cmyk.y); -+ cmykColor[3] = colToByte(cmyk.k); -+ -+ digit = cmykColor[comp] / 16; -+ hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); -+ digit = cmykColor[comp] % 16; -+ hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); -+ if (i >= 64) { -+ hexBuf[i++] = '\n'; -+ writePSBuf(hexBuf, i); -+ i = 0; -+ } -+ } - } -- } -- } else { -- // Hex color image -- for (x = 0; x < w; ++x) { -- digit = p[4*x + comp] / 16; -- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); -- digit = p[4*x + comp] % 16; -- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); -- if (i >= 64) { -- hexBuf[i++] = '\n'; -- writePSBuf(hexBuf, i); -- i = 0; -+ } -+ p -= bitmap->getRowSize(); -+ } -+ delete rgbCS; -+ break; -+ default: -+ for (y = 0; y < h; ++y) { -+ for (comp = 0; comp < 4; ++comp) { -+ if (useBinary) { -+ // Binary color image -+ for (x = 0; x < w; ++x) { -+ hexBuf[i++] = p[4*x + comp]; -+ if (i >= 64) { -+ writePSBuf(hexBuf, i); -+ i = 0; -+ } -+ } -+ } else { -+ // Hex color image -+ for (x = 0; x < w; ++x) { -+ digit = p[4*x + comp] / 16; -+ hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); -+ digit = p[4*x + comp] % 16; -+ hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); -+ if (i >= 64) { -+ hexBuf[i++] = '\n'; -+ writePSBuf(hexBuf, i); -+ i = 0; -+ } -+ } - } -- } -- } -- } -- p -= bitmap->getRowSize(); -+ } -+ p -= bitmap->getRowSize(); -+ } -+ break; - } - } - if (i != 0) { --- -2.21.0 - diff --git a/poppler-0.84.0-MacroPushRequiredVars.patch b/poppler-0.84.0-MacroPushRequiredVars.patch deleted file mode 100644 index 3d47d81..0000000 --- a/poppler-0.84.0-MacroPushRequiredVars.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 25feab2736d35ca707bde173b4a7d548da342211 Mon Sep 17 00:00:00 2001 -From: Marek Kasik -Date: Thu, 2 Jan 2020 13:40:40 +0100 -Subject: [PATCH] Revert Remove unused MacroPushRequiredVars.cmake - -This is needed by the QT4 removal revert. ---- - cmake/modules/MacroPushRequiredVars.cmake | 46 +++++++++++++++++++++++ - 1 file changed, 46 insertions(+) - create mode 100644 cmake/modules/MacroPushRequiredVars.cmake - -diff --git a/cmake/modules/MacroPushRequiredVars.cmake b/cmake/modules/MacroPushRequiredVars.cmake -new file mode 100644 -index 00000000..35a6df5e ---- /dev/null -+++ b/cmake/modules/MacroPushRequiredVars.cmake -@@ -0,0 +1,46 @@ -+# this module defines two macros: -+# MACRO_PUSH_REQUIRED_VARS() -+# and -+# MACRO_POP_REQUIRED_VARS() -+# use these if you call cmake macros which use -+# any of the CMAKE_REQUIRED_XXX variables -+# -+# Usage: -+# MACRO_PUSH_REQUIRED_VARS() -+# SET(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -DSOME_MORE_DEF) -+# CHECK_FUNCTION_EXISTS(...) -+# MACRO_POP_REQUIRED_VARS() -+ -+# Copyright (c) 2006, Alexander Neundorf, -+# -+# Redistribution and use is allowed according to the terms of the BSD license. -+# For details see the accompanying COPYING-CMAKE-SCRIPTS file. -+ -+MACRO(MACRO_PUSH_REQUIRED_VARS) -+ -+ IF(NOT DEFINED _PUSH_REQUIRED_VARS_COUNTER) -+ SET(_PUSH_REQUIRED_VARS_COUNTER 0) -+ ENDIF(NOT DEFINED _PUSH_REQUIRED_VARS_COUNTER) -+ -+ MATH(EXPR _PUSH_REQUIRED_VARS_COUNTER "${_PUSH_REQUIRED_VARS_COUNTER}+1") -+ -+ SET(_CMAKE_REQUIRED_INCLUDES_SAVE_${_PUSH_REQUIRED_VARS_COUNTER} ${CMAKE_REQUIRED_INCLUDES}) -+ SET(_CMAKE_REQUIRED_DEFINITIONS_SAVE_${_PUSH_REQUIRED_VARS_COUNTER} ${CMAKE_REQUIRED_DEFINITIONS}) -+ SET(_CMAKE_REQUIRED_LIBRARIES_SAVE_${_PUSH_REQUIRED_VARS_COUNTER} ${CMAKE_REQUIRED_LIBRARIES}) -+ SET(_CMAKE_REQUIRED_FLAGS_SAVE_${_PUSH_REQUIRED_VARS_COUNTER} ${CMAKE_REQUIRED_FLAGS}) -+ENDMACRO(MACRO_PUSH_REQUIRED_VARS) -+ -+MACRO(MACRO_POP_REQUIRED_VARS) -+ -+# don't pop more than we pushed -+ IF("${_PUSH_REQUIRED_VARS_COUNTER}" GREATER "0") -+ -+ SET(CMAKE_REQUIRED_INCLUDES ${_CMAKE_REQUIRED_INCLUDES_SAVE_${_PUSH_REQUIRED_VARS_COUNTER}}) -+ SET(CMAKE_REQUIRED_DEFINITIONS ${_CMAKE_REQUIRED_DEFINITIONS_SAVE_${_PUSH_REQUIRED_VARS_COUNTER}}) -+ SET(CMAKE_REQUIRED_LIBRARIES ${_CMAKE_REQUIRED_LIBRARIES_SAVE_${_PUSH_REQUIRED_VARS_COUNTER}}) -+ SET(CMAKE_REQUIRED_FLAGS ${_CMAKE_REQUIRED_FLAGS_SAVE_${_PUSH_REQUIRED_VARS_COUNTER}}) -+ -+ MATH(EXPR _PUSH_REQUIRED_VARS_COUNTER "${_PUSH_REQUIRED_VARS_COUNTER}-1") -+ ENDIF("${_PUSH_REQUIRED_VARS_COUNTER}" GREATER "0") -+ -+ENDMACRO(MACRO_POP_REQUIRED_VARS) --- -2.24.1 - diff --git a/poppler-0.90.0-qt4-update.patch b/poppler-0.90.0-qt4-update.patch deleted file mode 100644 index 725a016..0000000 --- a/poppler-0.90.0-qt4-update.patch +++ /dev/null @@ -1,383 +0,0 @@ ---- poppler-0.90.0/qt4/src/poppler-annotation.cc -+++ poppler-0.90.0/qt4/src/poppler-annotation.cc -@@ -789,7 +789,7 @@ Link* AnnotationPrivate::additionalActio - case Annotation::PageInvisibleAction: actionType = Annot::actionPageInvisible; break; - } - -- ::LinkAction *linkAction = nullptr; -+ std::unique_ptr<::LinkAction> linkAction = nullptr; - if ( pdfAnnot->getType() == Annot::typeScreen ) - linkAction = static_cast( pdfAnnot )->getAdditionalAction( actionType ); - else -@@ -798,7 +798,7 @@ Link* AnnotationPrivate::additionalActio - Link *link = nullptr; - - if ( linkAction ) -- link = PageData::convertLinkActionToLink( linkAction, parentDoc, QRectF() ); -+ link = PageData::convertLinkActionToLink( linkAction.get(), parentDoc, QRectF() ); - - return link; - } ---- poppler-0.90.0/qt4/src/poppler-document.cc -+++ poppler-0.90.0/qt4/src/poppler-document.cc -@@ -57,8 +57,6 @@ - - namespace Poppler { - -- int DocumentData::count = 0; -- - Document *Document::load(const QString &filePath, const QByteArray &ownerPassword, - const QByteArray &userPassword) - { -@@ -633,7 +631,16 @@ namespace Poppler { - void Document::setColorDisplayProfile(void* outputProfileA) - { - #if defined(USE_CMS) -- GfxColorSpace::setDisplayProfile((cmsHPROFILE)outputProfileA); -+ if (m_doc->m_sRGBProfile && m_doc->m_sRGBProfile.get() == outputProfileA) { -+ // Catch the special case that the user passes the sRGB profile -+ m_doc->m_displayProfile = m_doc->m_sRGBProfile; -+ return; -+ } -+ if (m_doc->m_displayProfile && m_doc->m_displayProfile.get() == outputProfileA) { -+ // Catch the special case that the user passes the display profile -+ return; -+ } -+ m_doc->m_displayProfile = make_GfxLCMSProfilePtr(outputProfileA); - #else - Q_UNUSED(outputProfileA); - #endif -@@ -642,9 +649,8 @@ namespace Poppler { - void Document::setColorDisplayProfileName(const QString &name) - { - #if defined(USE_CMS) -- GooString *profileName = QStringToGooString( name ); -- GfxColorSpace::setDisplayProfileName(profileName); -- delete profileName; -+ void* rawprofile = cmsOpenProfileFromFile(name.toLocal8Bit().constData(),"r"); -+ m_doc->m_displayProfile = make_GfxLCMSProfilePtr(rawprofile); - #else - Q_UNUSED(name); - #endif -@@ -653,7 +659,10 @@ namespace Poppler { - void* Document::colorRgbProfile() const - { - #if defined(USE_CMS) -- return (void*)GfxColorSpace::getRGBProfile(); -+ if (!m_doc->m_sRGBProfile) { -+ m_doc->m_sRGBProfile = make_GfxLCMSProfilePtr(cmsCreate_sRGBProfile()); -+ } -+ return m_doc->m_sRGBProfile.get(); - #else - return NULL; - #endif -@@ -662,7 +671,7 @@ namespace Poppler { - void* Document::colorDisplayProfile() const - { - #if defined(USE_CMS) -- return (void*)GfxColorSpace::getDisplayProfile(); -+ return m_doc->m_displayProfile.get(); - #else - return NULL; - #endif ---- poppler-0.90.0/qt4/src/poppler-link.cc -+++ poppler-0.90.0/qt4/src/poppler-link.cc -@@ -232,7 +232,7 @@ class LinkMoviePrivate : public LinkPriv - if ( data.namedDest && !ld && !data.externalDest ) - { - deleteDest = true; -- ld = data.doc->doc->findDest( data.namedDest ); -+ ld = data.doc->doc->findDest( data.namedDest ).release(); - } - // in case this destination was named one, and it was not resolved - if ( data.namedDest && !ld ) ---- poppler-0.90.0/qt4/src/poppler-page.cc -+++ poppler-0.90.0/qt4/src/poppler-page.cc -@@ -110,30 +110,30 @@ Link* PageData::convertLinkActionToLink( - - case actionNamed: - { -- const char * name = ((LinkNamed *)a)->getName()->c_str(); -- if ( !strcmp( name, "NextPage" ) ) -+ const std::string& name = ((LinkNamed *)a)->getName(); -+ if ( name == "NextPage" ) - popplerLink = new LinkAction( linkArea, LinkAction::PageNext ); -- else if ( !strcmp( name, "PrevPage" ) ) -+ else if ( name == "PrevPage" ) - popplerLink = new LinkAction( linkArea, LinkAction::PagePrev ); -- else if ( !strcmp( name, "FirstPage" ) ) -+ else if ( name == "FirstPage" ) - popplerLink = new LinkAction( linkArea, LinkAction::PageFirst ); -- else if ( !strcmp( name, "LastPage" ) ) -+ else if ( name == "LastPage" ) - popplerLink = new LinkAction( linkArea, LinkAction::PageLast ); -- else if ( !strcmp( name, "GoBack" ) ) -+ else if ( name == "GoBack" ) - popplerLink = new LinkAction( linkArea, LinkAction::HistoryBack ); -- else if ( !strcmp( name, "GoForward" ) ) -+ else if ( name == "GoForward" ) - popplerLink = new LinkAction( linkArea, LinkAction::HistoryForward ); -- else if ( !strcmp( name, "Quit" ) ) -+ else if ( name == "Quit" ) - popplerLink = new LinkAction( linkArea, LinkAction::Quit ); -- else if ( !strcmp( name, "GoToPage" ) ) -+ else if ( name == "GoToPage" ) - popplerLink = new LinkAction( linkArea, LinkAction::GoToPage ); -- else if ( !strcmp( name, "Find" ) ) -+ else if ( name == "Find" ) - popplerLink = new LinkAction( linkArea, LinkAction::Find ); -- else if ( !strcmp( name, "FullScreen" ) ) -+ else if ( name == "FullScreen" ) - popplerLink = new LinkAction( linkArea, LinkAction::Presentation ); -- else if ( !strcmp( name, "Print" ) ) -+ else if ( name == "Print" ) - popplerLink = new LinkAction( linkArea, LinkAction::Print ); -- else if ( !strcmp( name, "Close" ) ) -+ else if ( name == "Close" ) - { - // acroread closes the document always, doesnt care whether - // its presentation mode or not -@@ -149,7 +149,7 @@ Link* PageData::convertLinkActionToLink( - - case actionURI: - { -- popplerLink = new LinkBrowse( linkArea, ((LinkURI *)a)->getURI()->c_str() ); -+ popplerLink = new LinkBrowse( linkArea, ((LinkURI *)a)->getURI().c_str() ); - } - break; - -@@ -362,6 +362,10 @@ QImage Page::renderToImage(double xres, - splash_output.setFreeTypeHinting(m_page->parentDoc->m_hints & Document::TextHinting ? true : false, - m_page->parentDoc->m_hints & Document::TextSlightHinting ? true : false); - -+#ifdef USE_CMS -+ splash_output.setDisplayProfile(m_page->parentDoc->m_displayProfile); -+#endif -+ - splash_output.startDoc(m_page->parentDoc->doc); - - m_page->parentDoc->doc->displayPageSlice(&splash_output, m_page->index + 1, xres, yres, -@@ -442,6 +447,11 @@ bool Page::renderToPainter(QPainter* pai - painter->translate(x == -1 ? 0 : -x, y == -1 ? 0 : -y); - ArthurOutputDev arthur_output(painter); - arthur_output.startDoc(m_page->parentDoc->doc->getXRef()); -+ -+#ifdef USE_CMS -+ arthur_output.setDisplayProfile(m_page->parentDoc->m_displayProfile); -+#endif -+ - m_page->parentDoc->doc->displayPageSlice(&arthur_output, - m_page->index + 1, - xres, -@@ -671,12 +681,11 @@ Link *Page::action( PageAction act ) con - Dict *dict = o.getDict(); - const char *key = act == Page::Opening ? "O" : "C"; - Object o2 = dict->lookup((char*)key); -- ::LinkAction *lact = ::LinkAction::parseAction(&o2, m_page->parentDoc->doc->getCatalog()->getBaseURI() ); -+ std::unique_ptr<::LinkAction> lact = ::LinkAction::parseAction(&o2, m_page->parentDoc->doc->getCatalog()->getBaseURI() ); - Link *popplerLink = NULL; - if (lact != NULL) - { -- popplerLink = m_page->convertLinkActionToLink(lact, QRectF()); -- delete lact; -+ popplerLink = m_page->convertLinkActionToLink(lact.get(), QRectF()); - } - return popplerLink; - } ---- poppler-0.90.0/qt4/src/poppler-private.cc -+++ poppler-0.90.0/qt4/src/poppler-private.cc -@@ -49,15 +49,13 @@ namespace Debug { - - } - -- static UnicodeMap *utf8Map = 0; -- - void setDebugErrorFunction(PopplerDebugFunc function, const QVariant &closure) - { - Debug::debugFunction = function ? function : Debug::qDebugDebugFunction; - Debug::debugClosure = closure; - } - -- static void qt4ErrorFunction(void * /*data*/, ErrorCategory /*category*/, Goffset pos, const char *msg) -+ void qt4ErrorFunction(ErrorCategory /*category*/, Goffset pos, const char *msg) - { - QString emsg; - -@@ -74,12 +72,7 @@ namespace Debug { - } - - QString unicodeToQString(const Unicode* u, int len) { -- if (!utf8Map) -- { -- GooString enc("UTF-8"); -- utf8Map = globalParams->getUnicodeMap(&enc); -- utf8Map->incRefCnt(); -- } -+ const UnicodeMap *utf8Map = globalParams->getUtf8Map(); - - // ignore the last character if it is 0x0 - if ((len > 0) && (u[len - 1] == 0)) -@@ -99,34 +92,25 @@ namespace Debug { - } - - QString UnicodeParsedString(const GooString *s1) { -- if ( !s1 || s1->getLength() == 0 ) -+ return (s1) ? UnicodeParsedString(s1->toStr()) : QString(); -+ } -+ -+ QString UnicodeParsedString(const std::string& s1) { -+ if ( s1.empty() ) - return QString(); - -- const char *cString; -- int stringLength; -- bool deleteCString; -- if ( ( s1->getChar(0) & 0xff ) == 0xfe && ( s1->getLength() > 1 && ( s1->getChar(1) & 0xff ) == 0xff ) ) -- { -- cString = s1->c_str(); -- stringLength = s1->getLength(); -- deleteCString = false; -- } -- else -+ if ( GooString::hasUnicodeMarker(s1) || GooString::hasUnicodeMarkerLE(s1) ) - { -- cString = pdfDocEncodingToUTF16(s1, &stringLength); -- deleteCString = true; -+ return QString::fromUtf16(reinterpret_cast(s1.c_str()), s1.size() / 2); - } -- -- QString result; -- // i = 2 to skip the unicode marker -- for ( int i = 2; i < stringLength; i += 2 ) -+ else - { -- const Unicode u = ( ( cString[i] & 0xff ) << 8 ) | ( cString[i+1] & 0xff ); -- result += QChar( u ); -- } -- if (deleteCString) -+ int stringLength; -+ const char *cString = pdfDocEncodingToUTF16(s1, &stringLength); -+ auto result = QString::fromUtf16(reinterpret_cast(cString), stringLength / 2); - delete[] cString; -- return result; -+ return result; -+ } - } - - GooString *QStringToUnicodeGooString(const QString &s) { -@@ -221,7 +205,7 @@ namespace Debug { - case actionURI: - { - const LinkURI * u = static_cast< const LinkURI * >( a ); -- e->setAttribute( "DestinationURI", u->getURI()->c_str() ); -+ e->setAttribute( "DestinationURI", u->getURI().c_str() ); - } - default: ; - } -@@ -233,13 +217,6 @@ namespace Debug { - delete (OptContentModel *)m_optContentModel; - delete doc; - delete m_fontInfoIterator; -- -- count --; -- if ( count == 0 ) -- { -- utf8Map = nullptr; -- globalParams.reset(); -- } - } - - void DocumentData::init() -@@ -249,14 +226,6 @@ namespace Debug { - paperColor = Qt::white; - m_hints = 0; - m_optContentModel = 0; -- -- if ( count == 0 ) -- { -- utf8Map = nullptr; -- globalParams = std::make_unique(); -- setErrorCallback(qt4ErrorFunction, nullptr); -- } -- count ++; - } - - ---- poppler-0.90.0/qt4/src/poppler-private.h -+++ poppler-0.90.0/qt4/src/poppler-private.h -@@ -55,6 +55,8 @@ class FormWidget; - QString unicodeToQString(const Unicode* u, int len); - - QString UnicodeParsedString(const GooString *s1); -+ -+ QString UnicodeParsedString(const std::string& s1); - - GooString *QStringToUnicodeGooString(const QString &s); - -@@ -65,7 +67,7 @@ namespace Poppler { - - GooString *QDateTimeToUnicodeGooString(const QDateTime &dt); - -- void qt4ErrorFunction(int pos, char *msg, va_list args); -+ void qt4ErrorFunction(ErrorCategory /*category*/, Goffset pos, const char *msg); - - class LinkDestinationData - { -@@ -65,9 +67,10 @@ namespace Poppler { - bool externalDest; - }; - -- class DocumentData { -+ class DocumentData : private GlobalParamsIniter { - public: -- DocumentData(const QString &filePath, GooString *ownerPassword, GooString *userPassword) -+ DocumentData(const QString &filePath, GooString *ownerPassword, GooString *userPassword) : -+ GlobalParamsIniter(qt4ErrorFunction) - { - init(); - m_filePath = filePath; -@@ -102,7 +105,8 @@ namespace Poppler { - delete userPassword; - } - -- DocumentData(const QByteArray &data, GooString *ownerPassword, GooString *userPassword) -+ DocumentData(const QByteArray &data, GooString *ownerPassword, GooString *userPassword) : -+ GlobalParamsIniter(qt4ErrorFunction) - { - fileContents = data; - MemStream *str = new MemStream((char*)fileContents.data(), 0, fileContents.length(), Object(objNull)); -@@ -148,7 +152,10 @@ namespace Poppler { - QPointer m_optContentModel; - QColor paperColor; - int m_hints; -- static int count; -+#ifdef USE_CMS -+ GfxLCMSProfilePtr m_sRGBProfile; -+ GfxLCMSProfilePtr m_displayProfile; -+#endif - }; - - class FontInfoData ---- poppler-0.90.0/qt4/src/poppler-ps-converter.cc -+++ poppler-0.90.0/qt4/src/poppler-ps-converter.cc -@@ -235,7 +235,7 @@ bool PSConverter::convert() - d->marginBottom, - d->paperWidth - d->marginRight, - d->paperHeight - d->marginTop, -- (d->opts & ForceRasterization)); -+ (d->opts & ForceRasterization) ? psAlwaysRasterize : psRasterizeWhenNeeded); - - if (d->opts & StrictMargins) - { ---- poppler-0.90.0/qt4/src/poppler-sound.cc -+++ poppler-0.90.0/qt4/src/poppler-sound.cc -@@ -75,8 +75,7 @@ QString SoundObject::url() const - if ( m_soundData->m_type != SoundObject::External ) - return QString(); - -- const GooString * goo = m_soundData->m_soundObj->getFileName(); -- return goo ? QString( goo->c_str() ) : QString(); -+ return QString( m_soundData->m_soundObj->getFileName().c_str() ); - } - - QByteArray SoundObject::data() const diff --git a/poppler-gcc11.patch b/poppler-gcc11.patch index f6614c3..1a78020 100644 --- a/poppler-gcc11.patch +++ b/poppler-gcc11.patch @@ -11,16 +11,17 @@ index 26a51b4..27be2b9 100644 if (g_once_init_enter (&g_define_type_id__volatile)) { static const G@Type@Value values[] = { + diff --git a/glib/poppler-private.h b/glib/poppler-private.h index 7726ec7..436bca5 100644 --- a/glib/poppler-private.h +++ b/glib/poppler-private.h @@ -167,7 +167,7 @@ gboolean _poppler_convert_pdf_date_to_gtime (const GooString *date, - GType \ - type_name##_get_type (void) \ - { \ -- static volatile gsize g_define_type_id__volatile = 0; \ -+ static gsize g_define_type_id__volatile = 0; \ - if (g_once_init_enter (&g_define_type_id__volatile)) { \ - GType g_define_type_id = \ - g_boxed_type_register_static (g_intern_static_string (#TypeName), \ + #define POPPLER_DEFINE_BOXED_TYPE(TypeName, type_name, copy_func, free_func) \ + GType type_name##_get_type(void) \ + { \ +- static volatile gsize g_define_type_id__volatile = 0; \ ++ static gsize g_define_type_id__volatile = 0; \ + if (g_once_init_enter(&g_define_type_id__volatile)) { \ + GType g_define_type_id = g_boxed_type_register_static(g_intern_static_string(#TypeName), (GBoxedCopyFunc)copy_func, (GBoxedFreeFunc)free_func); \ + g_once_init_leave(&g_define_type_id__volatile, g_define_type_id); \ diff --git a/poppler.spec b/poppler.spec index f474b75..930b852 100644 --- a/poppler.spec +++ b/poppler.spec @@ -1,10 +1,10 @@ -%global test_sha 45f55f1e03b9bf3fbd334c31776b6f5e472889ec -%global test_date 2018-12-18 +%global test_sha 03a4b9eb854a06a83c465e82de601796c458bbe9 +%global test_date 2021-01-11 Summary: PDF rendering library Name: poppler -Version: 0.90.0 -Release: 8%{?dist} +Version: 21.01.0 +Release: 1%{?dist} License: (GPLv2 or GPLv3) and GPLv2+ and LGPLv2+ and MIT URL: http://poppler.freedesktop.org/ Source0: http://poppler.freedesktop.org/poppler-%{version}.tar.xz @@ -14,27 +14,12 @@ Source1: %{name}-test-%{test_date}-%{test_sha}.tar.xz # https://bugzilla.redhat.com/show_bug.cgi?id=1185007 Patch0: poppler-0.30.0-rotated-words-selection.patch -%if 0%{?fedora} -Patch1: 0001-Revert-Remove-the-Qt4-frontend.patch - -Patch3: poppler-0.67.0-qt4-const.patch -%endif - -# https://bugzilla.redhat.com/show_bug.cgi?id=1696636 -Patch4: poppler-0.73.0-PSOutputDev-buffer-read.patch - -Patch5: poppler-0.84.0-MacroPushRequiredVars.patch - -%if 0%{?fedora} -# https://bugzilla.redhat.com/show_bug.cgi?id=1673727 -Patch6: poppler-0.90.0-qt4-update.patch -%endif - -Patch7: poppler-0.90.0-position-independent-code.patch +Patch1: poppler-0.90.0-position-independent-code.patch # Bogus volatiles detected by gcc-11 -Patch8: %{name}-gcc11.patch +Patch2: %{name}-gcc11.patch +BuildRequires: make BuildRequires: cmake BuildRequires: gcc-c++ BuildRequires: gettext-devel @@ -63,12 +48,6 @@ BuildRequires: pkgconfig(Qt5Gui) BuildRequires: pkgconfig(Qt5Test) BuildRequires: pkgconfig(Qt5Widgets) BuildRequires: pkgconfig(Qt5Xml) -%if 0%{?fedora} -BuildRequires: pkgconfig(QtCore) -BuildRequires: pkgconfig(QtGui) -BuildRequires: pkgconfig(QtTest) -BuildRequires: pkgconfig(QtXml) -%endif Requires: poppler-data @@ -108,27 +87,6 @@ BuildArch: noarch %description glib-doc %{summary}. -%if 0%{?fedora} -%package qt -Summary: Qt4 wrapper for poppler -Requires: %{name}%{?_isa} = %{version}-%{release} -%{?_qt4:Requires: qt4%{?_isa} >= %{_qt4_version}} -Obsoletes: poppler-qt4 < 0.16.0-3 -Provides: poppler-qt4 = %{version}-%{release} -%description qt -%{summary}. - -%package qt-devel -Summary: Development files for Qt4 wrapper -Requires: %{name}-qt%{?_isa} = %{version}-%{release} -Requires: %{name}-devel%{?_isa} = %{version}-%{release} -Obsoletes: poppler-qt4-devel < 0.16.0-3 -Provides: poppler-qt4-devel = %{version}-%{release} -Requires: qt4-devel -%description qt-devel -%{summary}. -%endif - %package qt5 Summary: Qt5 wrapper for poppler Requires: %{name}%{?_isa} = %{version}-%{release} @@ -168,6 +126,8 @@ other formats. %prep %autosetup -p1 -b 1 +chmod -x poppler/CairoFontEngine.cc + %build %cmake \ -DENABLE_CMS=lcms2 \ @@ -188,23 +148,14 @@ other formats. # verify pkg-config sanity/version export PKG_CONFIG_PATH=%{buildroot}%{_datadir}/pkgconfig:%{buildroot}%{_libdir}/pkgconfig test "$(pkg-config --modversion poppler)" = "%{version}" -test "$(pkg-config --modversion poppler-cairo)" = "%{version}" test "$(pkg-config --modversion poppler-cpp)" = "%{version}" test "$(pkg-config --modversion poppler-glib)" = "%{version}" -%if 0%{?fedora} -test "$(pkg-config --modversion poppler-qt4)" = "%{version}" -%endif test "$(pkg-config --modversion poppler-qt5)" = "%{version}" -test "$(pkg-config --modversion poppler-splash)" = "%{version}" %ldconfig_scriptlets %ldconfig_scriptlets glib -%if 0%{?fedora} -%ldconfig_scriptlets qt -%endif - %ldconfig_scriptlets qt5 %ldconfig_scriptlets cpp @@ -212,11 +163,10 @@ test "$(pkg-config --modversion poppler-splash)" = "%{version}" %files %doc README.md %license COPYING -%{_libdir}/libpoppler.so.101* +%{_libdir}/libpoppler.so.106* %files devel %{_libdir}/pkgconfig/poppler.pc -%{_libdir}/pkgconfig/poppler-splash.pc %{_libdir}/libpoppler.so %dir %{_includedir}/poppler/ # xpdf headers @@ -231,7 +181,6 @@ test "$(pkg-config --modversion poppler-splash)" = "%{version}" %files glib-devel %{_libdir}/pkgconfig/poppler-glib.pc -%{_libdir}/pkgconfig/poppler-cairo.pc %{_libdir}/libpoppler-glib.so %{_datadir}/gir-1.0/Poppler-0.18.gir %{_includedir}/poppler/glib/ @@ -240,16 +189,6 @@ test "$(pkg-config --modversion poppler-splash)" = "%{version}" %license COPYING %{_datadir}/gtk-doc/ -%if 0%{?fedora} -%files qt -%{_libdir}/libpoppler-qt4.so.4* - -%files qt-devel -%{_libdir}/libpoppler-qt4.so -%{_libdir}/pkgconfig/poppler-qt4.pc -%{_includedir}/poppler/qt4/ -%endif - %files qt5 %{_libdir}/libpoppler-qt5.so.1* @@ -271,6 +210,11 @@ test "$(pkg-config --modversion poppler-splash)" = "%{version}" %{_mandir}/man1/* %changelog +* Mon Jan 11 2021 Marek Kasik - 21.01.0-1 +- Update to 21.01.0 +- Remove the Qt4 frontend +- Resolves: #1673727 + * Mon Dec 07 2020 Marek Kasik - 0.90.0-8 - Build Qt4 frontend on Fedora only diff --git a/sources b/sources index a8b52cd..da75ca2 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (poppler-0.90.0.tar.xz) = 3b2a45c7fcdc41b0dad80b6454cd8bb50a6625537edbc537898790ef4b6425bb62e1934fd2aaa8565be9c045ab1ac40a8de2e939c5b5abf0254d8e6c833b4450 -SHA512 (poppler-test-2018-12-18-45f55f1e03b9bf3fbd334c31776b6f5e472889ec.tar.xz) = fa1d8c92ca5bc9ebd7453dfb78f34fb44d014621fe698aa4a3fa9bd17bd0d302ca6ba36f4dd46a1ef030c0b7a30729d4bacb6d01c5c67d429c897e4f5ab331e8 +SHA512 (poppler-test-2021-01-11-03a4b9eb854a06a83c465e82de601796c458bbe9.tar.xz) = 257133b261b07076d3207456e3edad324e29911a45a960d4953eb84813ac175bc65be713a10454b52b96711870fcbeee533fd0fd7de8550a87390e833b1af8c5 +SHA512 (poppler-21.01.0.tar.xz) = aec130446df73a2fc66851a563a14cb40299212a2de4a0d03668b0fecb28312fffa70d0a82431c774d0c0e3f7293788bd2bdf28c8136aa09ad80edbca4cf0ddd