diff --git a/Pdf4QtDocPageOrganizer/mainwindow.cpp b/Pdf4QtDocPageOrganizer/mainwindow.cpp index f5b8d7b..2895b22 100644 --- a/Pdf4QtDocPageOrganizer/mainwindow.cpp +++ b/Pdf4QtDocPageOrganizer/mainwindow.cpp @@ -33,6 +33,7 @@ #include #include #include +#include namespace pdfdocpage { @@ -345,6 +346,7 @@ void MainWindow::performOperation(Operation operation) case Operation::Clear: { m_model->clear(); + QPixmapCache::clear(); break; } case Operation::CloneSelection: diff --git a/Pdf4QtDocPageOrganizer/pageitemdelegate.cpp b/Pdf4QtDocPageOrganizer/pageitemdelegate.cpp index 39a7689..b65516b 100644 --- a/Pdf4QtDocPageOrganizer/pageitemdelegate.cpp +++ b/Pdf4QtDocPageOrganizer/pageitemdelegate.cpp @@ -19,8 +19,10 @@ #include "pageitemmodel.h" #include "pdfwidgetutils.h" #include "pdfpainterutils.h" +#include "pdfrenderer.h" #include +#include namespace pdfdocpage { @@ -62,9 +64,18 @@ void PageItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& opti QSize pageImageSize = rotatedPageSize.scaled(pageBoundingRect.size(), Qt::KeepAspectRatio).toSize(); QRect pageImageRect(pageBoundingRect.topLeft() + QPoint((pageBoundingRect.width() - pageImageSize.width()) / 2, (pageBoundingRect.height() - pageImageSize.height()) / 2), pageImageSize); - painter->setPen(QPen(Qt::black)); painter->setBrush(Qt::white); painter->drawRect(pageImageRect); + + QPixmap pageImagePixmap = getPageImagePixmap(item, pageImageRect); + if (!pageImagePixmap.isNull()) + { + painter->drawPixmap(pageImageRect, pageImagePixmap); + } + + painter->setPen(QPen(Qt::black)); + painter->setBrush(Qt::NoBrush); + painter->drawRect(pageImageRect); } int textOffset = pageBoundingRect.bottom() + verticalSpacing; @@ -122,4 +133,73 @@ void PageItemDelegate::setPageImageSize(QSize pageImageSize) } } +QPixmap PageItemDelegate::getPageImagePixmap(const PageGroupItem* item, QRect rect) const +{ + QPixmap pixmap; + + Q_ASSERT(item); + if (item->groups.empty()) + { + return pixmap; + } + + const PageGroupItem::GroupItem& groupItem = item->groups.front(); + if (groupItem.pageType == PT_Empty) + { + return pixmap; + } + + // Jakub Melka: generate key and see, if pixmap is not cached + QString key = QString("%1#%2#%3#%4#%5@%6x%7").arg(groupItem.documentIndex).arg(groupItem.imageIndex).arg(int(groupItem.pageAdditionalRotation)).arg(groupItem.pageIndex).arg(groupItem.pageType).arg(rect.width()).arg(rect.height()); + + if (!QPixmapCache::find(key, &pixmap)) + { + // We must draw the pixmap + pixmap = QPixmap(rect.width(), rect.height()); + pixmap.fill(Qt::transparent); + + switch (groupItem.pageType) + { + case pdfdocpage::PT_DocumentPage: + break; + + case pdfdocpage::PT_Image: + { + const auto& images = m_model->getImages(); + auto it = images.find(groupItem.imageIndex); + if (it != images.cend()) + { + const QImage& image = it->second.image; + if (!image.isNull()) + { + QRect drawRect(QPoint(0, 0), rect.size()); + QRect mediaBox(QPoint(0, 0), image.size()); + QMatrix matrix = pdf::PDFRenderer::createMediaBoxToDevicePointMatrix(mediaBox, drawRect, groupItem.pageAdditionalRotation); + + QPainter painter(&pixmap); + painter.setWorldMatrixEnabled(true); + painter.setWorldMatrix(matrix); + painter.translate(0, mediaBox.height()); + painter.scale(1.0, -1.0); + painter.drawImage(0, 0, image); + } + } + break; + } + + case pdfdocpage::PT_Empty: + Q_ASSERT(false); + break; + + default: + Q_ASSERT(false); + break; + } + + QPixmapCache::insert(key, pixmap); + } + + return pixmap; +} + } // namespace pdfdocpage diff --git a/Pdf4QtDocPageOrganizer/pageitemdelegate.h b/Pdf4QtDocPageOrganizer/pageitemdelegate.h index f14f663..0f8f645 100644 --- a/Pdf4QtDocPageOrganizer/pageitemdelegate.h +++ b/Pdf4QtDocPageOrganizer/pageitemdelegate.h @@ -24,6 +24,7 @@ namespace pdfdocpage { class PageItemModel; +struct PageGroupItem; class PageItemDelegate : public QAbstractItemDelegate { @@ -46,6 +47,8 @@ private: static constexpr int getVerticalSpacing() { return 5; } static constexpr int getHorizontalSpacing() { return 5; } + QPixmap getPageImagePixmap(const PageGroupItem* item, QRect rect) const; + PageItemModel* m_model; QSize m_pageImageSize; }; diff --git a/Pdf4QtLib/sources/pdfrenderer.cpp b/Pdf4QtLib/sources/pdfrenderer.cpp index c2bb672..92044f9 100644 --- a/Pdf4QtLib/sources/pdfrenderer.cpp +++ b/Pdf4QtLib/sources/pdfrenderer.cpp @@ -48,12 +48,22 @@ PDFRenderer::PDFRenderer(const PDFDocument* document, Q_ASSERT(document); } -QMatrix PDFRenderer::createPagePointToDevicePointMatrix(const PDFPage* page, const QRectF& rectangle) +QMatrix PDFRenderer::createPagePointToDevicePointMatrix(const PDFPage* page, + const QRectF& rectangle, + PageRotation extraRotation) { - QRectF mediaBox = page->getRotatedMediaBox(); + PageRotation pageRotation = getPageRotationCombined(page->getPageRotation(), extraRotation); + QRectF mediaBox = page->getRotatedBox(page->getMediaBox(), pageRotation); + return createMediaBoxToDevicePointMatrix(mediaBox, rectangle, pageRotation); +} + +QMatrix PDFRenderer::createMediaBoxToDevicePointMatrix(const QRectF& mediaBox, + const QRectF& rectangle, + PageRotation rotation) +{ QMatrix matrix; - switch (page->getPageRotation()) + switch (rotation) { case PageRotation::None: { diff --git a/Pdf4QtLib/sources/pdfrenderer.h b/Pdf4QtLib/sources/pdfrenderer.h index b2c192f..3baa00a 100644 --- a/Pdf4QtLib/sources/pdfrenderer.h +++ b/Pdf4QtLib/sources/pdfrenderer.h @@ -97,7 +97,18 @@ public: /// from page's media box to the target rectangle. /// \param page Page, for which we want to create matrix /// \param rectangle Page rectangle, to which is page media box transformed - static QMatrix createPagePointToDevicePointMatrix(const PDFPage* page, const QRectF& rectangle); + /// \param extraRotation Extra rotation applied to the page rotation + static QMatrix createPagePointToDevicePointMatrix(const PDFPage* page, + const QRectF& rectangle, + PageRotation extraRotation = PageRotation::None); + + /// Creates media box to device point matrix for the given media box. + /// \param mediaBox Media box + /// \param rectangle Page rectangle, to which is page media box transformed + /// \param rotation Rotation + static QMatrix createMediaBoxToDevicePointMatrix(const QRectF& mediaBox, + const QRectF& rectangle, + PageRotation rotation); /// Returns default renderer features static constexpr Features getDefaultFeatures() { return Features(Antialiasing | TextAntialiasing | ClipToCropBox | DisplayAnnotations); }