DocPage Organizer: Preview image painting

This commit is contained in:
Jakub Melka 2021-07-25 18:00:08 +02:00
parent 4570b12359
commit 7cc02ae51c
5 changed files with 111 additions and 5 deletions

View File

@ -33,6 +33,7 @@
#include <QToolBar>
#include <QDesktopServices>
#include <QImageReader>
#include <QPixmapCache>
namespace pdfdocpage
{
@ -345,6 +346,7 @@ void MainWindow::performOperation(Operation operation)
case Operation::Clear:
{
m_model->clear();
QPixmapCache::clear();
break;
}
case Operation::CloneSelection:

View File

@ -19,8 +19,10 @@
#include "pageitemmodel.h"
#include "pdfwidgetutils.h"
#include "pdfpainterutils.h"
#include "pdfrenderer.h"
#include <QPainter>
#include <QPixmapCache>
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

View File

@ -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;
};

View File

@ -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:
{

View File

@ -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); }