From 69abeef28a9cebca4f0394a26c46f5d3f2248a26 Mon Sep 17 00:00:00 2001 From: Paul Gideon Dann Date: Wed, 4 Apr 2018 16:36:56 +0100 Subject: [PATCH 1/2] Cairo backend added to Qt5 wrapper --- qt5/src/CMakeLists.txt | 15 ++++++++ qt5/src/poppler-document.cc | 3 ++ qt5/src/poppler-page.cc | 70 +++++++++++++++++++++++++++++++++++++ qt5/src/poppler-qt5.h | 3 +- qt5/tests/CMakeLists.txt | 5 +++ 5 files changed, 95 insertions(+), 1 deletion(-) diff --git a/qt5/src/CMakeLists.txt b/qt5/src/CMakeLists.txt index 53568ccb..1b0405de 100644 --- a/qt5/src/CMakeLists.txt +++ b/qt5/src/CMakeLists.txt @@ -5,6 +5,11 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ) +if (HAVE_CAIRO) + include_directories(${CAIRO_INCLUDE_DIRS}) + add_definitions(${CAIRO_CFLAGS}) +endif (HAVE_CAIRO) + set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) @@ -36,6 +41,13 @@ set(poppler_qt5_SRCS QPainterOutputDev.cc poppler-version.cpp ) +if (HAVE_CAIRO) + set(poppler_qt5_SRCS ${poppler_qt5_SRCS} + ${CMAKE_SOURCE_DIR}/poppler/CairoOutputDev.cc + ${CMAKE_SOURCE_DIR}/poppler/CairoRescaleBox.cc + ${CMAKE_SOURCE_DIR}/poppler/CairoFontEngine.cc + ) +endif(HAVE_CAIRO) add_library(poppler-qt5 ${poppler_qt5_SRCS}) generate_export_header(poppler-qt5 BASE_NAME poppler-qt5 EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/poppler-export.h") set_target_properties(poppler-qt5 PROPERTIES VERSION 1.32.0 SOVERSION 1) @@ -44,6 +56,9 @@ if(MINGW AND BUILD_SHARED_LIBS) set_target_properties(poppler-qt5 PROPERTIES SUFFIX "-${POPPLER_QT5_SOVERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}") endif() target_link_libraries(poppler-qt5 poppler Qt5::Core Qt5::Gui Qt5::Xml Freetype::Freetype) +if (HAVE_CAIRO) + target_link_libraries(poppler-qt5 ${CAIRO_LIBRARIES}) +endif (HAVE_CAIRO) if (ENABLE_NSS3) target_include_directories(poppler-qt5 SYSTEM PRIVATE ${NSS3_INCLUDE_DIRS}) endif() diff --git a/qt5/src/poppler-document.cc b/qt5/src/poppler-document.cc index 6daed698..09d7ac96 100644 --- a/qt5/src/poppler-document.cc +++ b/qt5/src/poppler-document.cc @@ -710,6 +710,9 @@ QSet Document::availableRenderBackends() ret << Document::SplashBackend; ret << Document::QPainterBackend; ret << Document::ArthurBackend; // For backward compatibility +#if defined(HAVE_CAIRO) + ret << Document::CairoBackend; +#endif return ret; } diff --git a/qt5/src/poppler-page.cc b/qt5/src/poppler-page.cc index 853ee3b9..17798c1e 100644 --- a/qt5/src/poppler-page.cc +++ b/qt5/src/poppler-page.cc @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +68,9 @@ #include #include #include +#if defined(HAVE_CAIRO) +# include +#endif #include "poppler-private.h" #include "poppler-page-transition-private.h" @@ -597,6 +601,69 @@ QImage Page::renderToImage(double xres, double yres, int xPos, int yPos, int w, img = tmpimg; break; } + case Poppler::Document::CairoBackend: { +#if defined(HAVE_CAIRO) + CairoOutputDev *output_dev = new CairoOutputDev(); + output_dev->startDoc(m_page->parentDoc->doc); + int buffer_width, buffer_height, rotate; + cairo_surface_t *surface; + cairo_t *cairo; + + // If w or h are -1, that indicates the whole page, so we need to + // calculate how many pixels that corresponds to. Otherwise, we can use w + // or h directly for our buffer size. + const QSize pageSize = this->pageSize(); + if (w == -1) { + const double xscale = xres / 72.0; + const double width = pageSize.width();; + buffer_width = (int) ceil(width * xscale); + } else { + buffer_width = w; + } + if (h == -1) { + const double yscale = yres / 72.0; + const double height = pageSize.height(); + buffer_height = (int) ceil(height * yscale); + } else { + buffer_height = h; + } + + rotate = rotation + m_page->page->getRotate(); + + // FIXME: Okular never provides a rotation value, so I don't have any way + // of testing this right now. The result is that subpixels are ordered + // incorrectly when the page is rotated. + + //if (rotate == 90 || rotate == 270) { + // const double temp = height; + // height = width; + // width = temp; + //} + + img = QImage(buffer_width, buffer_height, QImage::Format_ARGB32); + img.fill(Qt::white); // Never transparent + + surface = cairo_image_surface_create_for_data( + img.bits(), + CAIRO_FORMAT_ARGB32, + buffer_width, buffer_height, + img.bytesPerLine()); + + cairo = cairo_create(surface); + output_dev->setCairo(cairo); + + m_page->parentDoc->doc->displayPageSlice( + output_dev, m_page->index + 1, xres, yres, rotation, false, true, + false, xPos, yPos, w, h); + + // Clean up + output_dev->setCairo(nullptr); + cairo_destroy(cairo); + cairo_surface_destroy(surface); + delete output_dev; +#endif + break; + } } if (shouldAbortRenderCallback && shouldAbortRenderCallback(payload)) { @@ -622,6 +689,9 @@ bool Page::renderToPainter(QPainter *painter, double xres, double yres, int x, i return renderToQPainter(&qpainter_output, painter, m_page, xres, yres, x, y, w, h, rotate, flags); } + case Poppler::Document::CairoBackend: { + return false; + } } return false; } diff --git a/qt5/src/poppler-qt5.h b/qt5/src/poppler-qt5.h index abeb4fdb..380461a3 100644 --- a/qt5/src/poppler-qt5.h +++ b/qt5/src/poppler-qt5.h @@ -1182,7 +1182,8 @@ public: { SplashBackend, ///< Splash backend ArthurBackend, ///< \deprecated The old name of the QPainter backend - QPainterBackend = ArthurBackend ///< @since 20.11 + QPainterBackend = ArthurBackend, ///< @since 20.11 + CairoBackend ///< Cairo backend }; /** diff --git a/qt5/tests/CMakeLists.txt b/qt5/tests/CMakeLists.txt index e610413a..26c45088 100644 --- a/qt5/tests/CMakeLists.txt +++ b/qt5/tests/CMakeLists.txt @@ -7,6 +7,11 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR}/../src ) +if (HAVE_CAIRO) + include_directories(${CAIRO_INCLUDE_DIRS}) + add_definitions(${CAIRO_CFLAGS}) +endif (HAVE_CAIRO) + macro(QT5_ADD_SIMPLETEST exe source) string(REPLACE "-" "" test_name ${exe}) set(${test_name}_SOURCES -- 2.41.0