summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2019-12-23 07:34:16 +0100
committerShawn Rutledge <shawn.rutledge@qt.io>2020-01-30 15:50:44 +0100
commit4f5f0705bc161ff95899fdb2c5fcdb4581bf15bb (patch)
tree39e1f225a24d893176b9d22bc46bddacaadfca38
parentd1749c375ea924390d19225b40ef2631b524849b (diff)
QPdfDocument and QPdfIOHandler: add scale and clip features
Like some other image plugins, the PDF plugin now supports ImageOption::ScaledClipRect and ScaledSize. Change-Id: Ie7278752e49c885cc4580f30af1ec5e6310f8334 Reviewed-by: Michal Klocek <michal.klocek@qt.io>
-rw-r--r--src/pdf/api/qpdfdocumentrenderoptions.h12
-rw-r--r--src/pdf/qpdfdocument.cpp34
-rw-r--r--src/plugins/imageformats/pdf/qpdfiohandler.cpp10
3 files changed, 51 insertions, 5 deletions
diff --git a/src/pdf/api/qpdfdocumentrenderoptions.h b/src/pdf/api/qpdfdocumentrenderoptions.h
index 99a5db2e3..873be0085 100644
--- a/src/pdf/api/qpdfdocumentrenderoptions.h
+++ b/src/pdf/api/qpdfdocumentrenderoptions.h
@@ -39,6 +39,7 @@
#include <QtPdf/qpdfnamespace.h>
#include <QtCore/QObject>
+#include <QtCore/QRect>
QT_BEGIN_NAMESPACE
@@ -53,6 +54,12 @@ public:
Q_DECL_CONSTEXPR QPdf::RenderFlags renderFlags() const Q_DECL_NOTHROW { return static_cast<QPdf::RenderFlags>(bits.renderFlags); }
Q_DECL_RELAXED_CONSTEXPR void setRenderFlags(QPdf::RenderFlags _renderFlags) Q_DECL_NOTHROW { bits.renderFlags = _renderFlags; }
+ Q_DECL_CONSTEXPR QRect scaledClipRect() const Q_DECL_NOTHROW { return m_clipRect; }
+ Q_DECL_RELAXED_CONSTEXPR void setScaledClipRect(const QRect &r) Q_DECL_NOTHROW { m_clipRect = r; }
+
+ Q_DECL_CONSTEXPR QSize scaledSize() const Q_DECL_NOTHROW { return m_scaledSize; }
+ Q_DECL_RELAXED_CONSTEXPR void setScaledSize(const QSize &s) Q_DECL_NOTHROW { m_scaledSize = s; }
+
private:
friend Q_DECL_CONSTEXPR inline bool operator==(QPdfDocumentRenderOptions lhs, QPdfDocumentRenderOptions rhs) Q_DECL_NOTHROW;
@@ -68,13 +75,16 @@ private:
Bits bits;
quint64 data;
};
+
+ QRect m_clipRect;
+ QSize m_scaledSize;
};
Q_DECLARE_TYPEINFO(QPdfDocumentRenderOptions, Q_PRIMITIVE_TYPE);
Q_DECL_CONSTEXPR inline bool operator==(QPdfDocumentRenderOptions lhs, QPdfDocumentRenderOptions rhs) Q_DECL_NOTHROW
{
- return lhs.data == rhs.data;
+ return lhs.data == rhs.data && lhs.m_clipRect == rhs.m_clipRect && lhs.m_scaledSize == rhs.m_scaledSize;
}
Q_DECL_CONSTEXPR inline bool operator!=(QPdfDocumentRenderOptions lhs, QPdfDocumentRenderOptions rhs) Q_DECL_NOTHROW
diff --git a/src/pdf/qpdfdocument.cpp b/src/pdf/qpdfdocument.cpp
index 4c4f8f24e..728bf1245 100644
--- a/src/pdf/qpdfdocument.cpp
+++ b/src/pdf/qpdfdocument.cpp
@@ -46,6 +46,7 @@
#include <QHash>
#include <QLoggingCategory>
#include <QMutex>
+#include <QVector2D>
QT_BEGIN_NAMESPACE
@@ -675,12 +676,41 @@ QImage QPdfDocument::render(int page, QSize imageSize, QPdfDocumentRenderOptions
if (renderFlags & QPdf::RenderPathAliased)
flags |= FPDF_RENDER_NO_SMOOTHPATH;
- FPDF_RenderPageBitmap(bitmap, pdfPage, 0, 0, result.width(), result.height(), rotation, flags);
+ if (renderOptions.scaledClipRect().isValid()) {
+ const QRect &clipRect = renderOptions.scaledClipRect();
+
+ // TODO take rotation into account, like cpdf_page.cpp lines 145-178
+ float x0 = clipRect.left();
+ float y0 = clipRect.top();
+ float x1 = clipRect.left();
+ float y1 = clipRect.bottom();
+ float x2 = clipRect.right();
+ float y2 = clipRect.top();
+ QSizeF origSize = pageSize(page);
+ QVector2D pageScale(1, 1);
+ if (!renderOptions.scaledSize().isNull()) {
+ pageScale = QVector2D(renderOptions.scaledSize().width() / float(origSize.width()),
+ renderOptions.scaledSize().height() / float(origSize.height()));
+ }
+ FS_MATRIX matrix {(x2 - x0) / result.width() * pageScale.x(),
+ (y2 - y0) / result.width() * pageScale.x(),
+ (x1 - x0) / result.height() * pageScale.y(),
+ (y1 - y0) / result.height() * pageScale.y(), -x0, -y0};
+
+ FS_RECTF clipRectF { 0, 0, float(imageSize.width()), float(imageSize.height()) };
+
+ FPDF_RenderPageBitmapWithMatrix(bitmap, pdfPage, &matrix, &clipRectF, flags);
+ qCDebug(qLcDoc) << "matrix" << matrix.a << matrix.b << matrix.c << matrix.d << matrix.e << matrix.f;
+ qCDebug(qLcDoc) << "page" << page << "region" << renderOptions.scaledClipRect()
+ << "size" << imageSize << "took" << timer.elapsed() << "ms";
+ } else {
+ FPDF_RenderPageBitmap(bitmap, pdfPage, 0, 0, result.width(), result.height(), rotation, flags);
+ qCDebug(qLcDoc) << "page" << page << "size" << imageSize << "took" << timer.elapsed() << "ms";
+ }
FPDFBitmap_Destroy(bitmap);
FPDF_ClosePage(pdfPage);
- qCDebug(qLcDoc) << "page" << page << imageSize << "took" << timer.elapsed() << "ms";
return result;
}
diff --git a/src/plugins/imageformats/pdf/qpdfiohandler.cpp b/src/plugins/imageformats/pdf/qpdfiohandler.cpp
index 9df85cf08..739e8b34c 100644
--- a/src/plugins/imageformats/pdf/qpdfiohandler.cpp
+++ b/src/plugins/imageformats/pdf/qpdfiohandler.cpp
@@ -98,7 +98,8 @@ bool QPdfIOHandler::read(QImage *image)
if (m_page < 0)
m_page = 0;
const bool xform = (m_clipRect.isValid() || m_scaledSize.isValid() || m_scaledClipRect.isValid());
- QSize finalSize = m_doc.pageSize(m_page).toSize();
+ QSize pageSize = m_doc.pageSize(m_page).toSize();
+ QSize finalSize = pageSize;
QRectF bounds;
if (xform && !finalSize.isEmpty()) {
bounds = QRectF(QPointF(0,0), QSizeF(finalSize));
@@ -112,6 +113,7 @@ bool QPdfIOHandler::read(QImage *image)
sc = QSizeF(qreal(m_scaledSize.width()) / finalSize.width(),
qreal(m_scaledSize.height()) / finalSize.height());
finalSize = m_scaledSize;
+ pageSize = m_scaledSize;
}
if (m_scaledClipRect.isValid()) {
tr2 = -m_scaledClipRect.topLeft();
@@ -133,9 +135,13 @@ bool QPdfIOHandler::read(QImage *image)
}
}
if (!finalSize.isEmpty()) {
+ QPdfDocumentRenderOptions options;
+ if (m_scaledClipRect.isValid())
+ options.setScaledClipRect(m_scaledClipRect);
+ options.setScaledSize(pageSize);
image->fill(m_backColor.rgba());
QPainter p(image);
- QImage pageImage = m_doc.render(m_page, finalSize);
+ QImage pageImage = m_doc.render(m_page, finalSize, options);
p.drawImage(0, 0, pageImage);
p.end();
}