diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2024-01-26 20:34:46 -0700 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2024-02-02 07:00:38 +0000 |
commit | 57774a5eba87bc1ba181effefe9dc614f2d3330c (patch) | |
tree | a93d063966d087a527049547cc6c503497dc3ef4 | |
parent | 5ed8d711773fed1c4ae9c541e755d0e68455d9eb (diff) |
QPdfView: use per-page scale factors to render search result rectangles
In FitToWidth and FitInView zoomModes, each page could potentially be a
different size; so QPdfViewPrivate::calculateDocumentLayout() loops over
all pages, calculating each pageSize and offset on the fly. m_zoomFactor
doesn't get updated; but QPdfViewPrivate::updateDocumentLayout() stores
the per-page zoom factors in m_documentLayout.pageGeometryAndScale.
screenScaleTransform() takes the page index as an argument, looks up the
per-page scale factor in those zoom modes, and QPdfView::paintEvent()
uses the per-page transform to paint the rectangles.
Pick-to: 6.5
Task-number: QTBUG-120764
Change-Id: I86308c8963ffadd2fdb6f36cf9f4696f75f550ed
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
(cherry picked from commit 2b96bbb922c1500b8d3b12cf2eb3052ded41c5c6)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 427c1e114ab2969bfb51b24d0401f7e0286b5873)
-rw-r--r-- | src/pdfwidgets/qpdfview.cpp | 68 | ||||
-rw-r--r-- | src/pdfwidgets/qpdfview_p.h | 4 |
2 files changed, 44 insertions, 28 deletions
diff --git a/src/pdfwidgets/qpdfview.cpp b/src/pdfwidgets/qpdfview.cpp index 8f4934eae..a67667fed 100644 --- a/src/pdfwidgets/qpdfview.cpp +++ b/src/pdfwidgets/qpdfview.cpp @@ -106,8 +106,9 @@ void QPdfViewPrivate::setViewport(QRect viewport) const QRect currentPageLine(m_viewport.x(), m_viewport.y() + m_viewport.height() * 0.4, m_viewport.width(), 2); int currentPage = 0; - for (auto it = m_documentLayout.pageGeometries.cbegin(); it != m_documentLayout.pageGeometries.cend(); ++it) { - const QRect pageGeometry = it.value(); + for (auto it = m_documentLayout.pageGeometryAndScale.cbegin(); + it != m_documentLayout.pageGeometryAndScale.cend(); ++it) { + const QRect pageGeometry = it.value().first; if (pageGeometry.intersects(currentPageLine)) { currentPage = it.key(); break; @@ -182,7 +183,7 @@ QPdfViewPrivate::DocumentLayout QPdfViewPrivate::calculateDocumentLayout() const if (!m_document || m_document->status() != QPdfDocument::Status::Ready) return documentLayout; - QHash<int, QRect> pageGeometries; + QHash<int, QPair<QRect, qreal>> pageGeometryAndScale; const int pageCount = m_document->pageCount(); @@ -194,24 +195,28 @@ QPdfViewPrivate::DocumentLayout QPdfViewPrivate::calculateDocumentLayout() const // calculate page sizes for (int page = startPage; page < endPage; ++page) { QSize pageSize; + qreal pageScale = m_zoomFactor; if (m_zoomMode == QPdfView::ZoomMode::Custom) { pageSize = QSizeF(m_document->pagePointSize(page) * m_screenResolution * m_zoomFactor).toSize(); } else if (m_zoomMode == QPdfView::ZoomMode::FitToWidth) { pageSize = QSizeF(m_document->pagePointSize(page) * m_screenResolution).toSize(); - const qreal factor = (qreal(m_viewport.width() - m_documentMargins.left() - m_documentMargins.right()) / - qreal(pageSize.width())); - pageSize *= factor; + pageScale = (qreal(m_viewport.width() - m_documentMargins.left() - m_documentMargins.right()) / + qreal(pageSize.width())); + pageSize *= pageScale; } else if (m_zoomMode == QPdfView::ZoomMode::FitInView) { const QSize viewportSize(m_viewport.size() + QSize(-m_documentMargins.left() - m_documentMargins.right(), -m_pageSpacing)); pageSize = QSizeF(m_document->pagePointSize(page) * m_screenResolution).toSize(); - pageSize = pageSize.scaled(viewportSize, Qt::KeepAspectRatio); + QSize scaledSize = pageSize.scaled(viewportSize, Qt::KeepAspectRatio); + // because of KeepAspectRatio, the ratio of widths should be the same as the ratio of heights + pageScale = qreal(scaledSize.width()) / qreal(pageSize.width()); + pageSize = scaledSize; } totalWidth = qMax(totalWidth, pageSize.width()); - pageGeometries[page] = QRect(QPoint(0, 0), pageSize); + pageGeometryAndScale[page] = {QRect(QPoint(0, 0), pageSize), pageScale}; } totalWidth += m_documentMargins.left() + m_documentMargins.right(); @@ -220,19 +225,19 @@ QPdfViewPrivate::DocumentLayout QPdfViewPrivate::calculateDocumentLayout() const // calculate page positions for (int page = startPage; page < endPage; ++page) { - const QSize pageSize = pageGeometries[page].size(); + const QSize pageSize = pageGeometryAndScale[page].first.size(); // center horizontal inside the viewport const int pageX = (qMax(totalWidth, m_viewport.width()) - pageSize.width()) / 2; - pageGeometries[page].moveTopLeft(QPoint(pageX, pageY)); + pageGeometryAndScale[page].first.moveTopLeft(QPoint(pageX, pageY)); pageY += pageSize.height() + m_pageSpacing; } pageY += m_documentMargins.bottom(); - documentLayout.pageGeometries = pageGeometries; + documentLayout.pageGeometryAndScale = pageGeometryAndScale; // calculate overall document size documentLayout.documentSize = QSize(totalWidth, pageY); @@ -242,16 +247,25 @@ QPdfViewPrivate::DocumentLayout QPdfViewPrivate::calculateDocumentLayout() const qreal QPdfViewPrivate::yPositionForPage(int pageNumber) const { - const auto it = m_documentLayout.pageGeometries.constFind(pageNumber); - if (it == m_documentLayout.pageGeometries.cend()) + const auto it = m_documentLayout.pageGeometryAndScale.constFind(pageNumber); + if (it == m_documentLayout.pageGeometryAndScale.cend()) return 0.0; - return (*it).y(); + return (*it).first.y(); } -QTransform QPdfViewPrivate::screenScaleTransform() const +QTransform QPdfViewPrivate::screenScaleTransform(int page) const { - const qreal scale = m_screenResolution * m_zoomFactor; + qreal scale = m_screenResolution * m_zoomFactor; + switch (m_zoomMode) { + case QPdfView::ZoomMode::FitToWidth: + case QPdfView::ZoomMode::FitInView: + scale = m_screenResolution * m_documentLayout.pageGeometryAndScale[page].second; + break; + default: + break; + } + return QTransform::fromScale(scale, scale); } @@ -573,9 +587,9 @@ void QPdfView::paintEvent(QPaintEvent *event) painter.fillRect(event->rect(), palette().brush(QPalette::Dark)); painter.translate(-d->m_viewport.x(), -d->m_viewport.y()); - for (auto it = d->m_documentLayout.pageGeometries.cbegin(); - it != d->m_documentLayout.pageGeometries.cend(); ++it) { - const QRect pageGeometry = it.value(); + for (auto it = d->m_documentLayout.pageGeometryAndScale.cbegin(); + it != d->m_documentLayout.pageGeometryAndScale.cend(); ++it) { + const QRect pageGeometry = it.value().first; if (pageGeometry.intersects(d->m_viewport)) { // page needs to be painted painter.fillRect(pageGeometry, Qt::white); @@ -588,7 +602,7 @@ void QPdfView::paintEvent(QPaintEvent *event) d->m_pageRenderer->requestPage(page, pageGeometry.size() * devicePixelRatioF()); } - const QTransform scaleTransform = d->screenScaleTransform(); + const QTransform scaleTransform = d->screenScaleTransform(page); #ifdef DEBUG_LINKS const QString fmt = u"page %1 @ %2, %3"_s; d->m_linkModel.setPage(page); @@ -656,10 +670,11 @@ void QPdfView::mousePressEvent(QMouseEvent *event) void QPdfView::mouseMoveEvent(QMouseEvent *event) { Q_D(QPdfView); - const QTransform screenInvTransform = d->screenScaleTransform().inverted(); - for (auto it = d->m_documentLayout.pageGeometries.cbegin(); it != d->m_documentLayout.pageGeometries.cend(); ++it) { + for (auto it = d->m_documentLayout.pageGeometryAndScale.cbegin(); + it != d->m_documentLayout.pageGeometryAndScale.cend(); ++it) { const int page = it.key(); - const QRect pageGeometry = it.value(); + const QTransform screenInvTransform = d->screenScaleTransform(page).inverted(); + const QRect pageGeometry = it.value().first; if (pageGeometry.contains(event->position().toPoint())) { const QPointF posInPoints = screenInvTransform.map(event->position() - pageGeometry.topLeft()); d->m_linkModel.setPage(page); @@ -674,10 +689,11 @@ void QPdfView::mouseMoveEvent(QMouseEvent *event) void QPdfView::mouseReleaseEvent(QMouseEvent *event) { Q_D(QPdfView); - const QTransform screenInvTransform = d->screenScaleTransform().inverted(); - for (auto it = d->m_documentLayout.pageGeometries.cbegin(); it != d->m_documentLayout.pageGeometries.cend(); ++it) { + for (auto it = d->m_documentLayout.pageGeometryAndScale.cbegin(); + it != d->m_documentLayout.pageGeometryAndScale.cend(); ++it) { const int page = it.key(); - const QRect pageGeometry = it.value(); + const QTransform screenInvTransform = d->screenScaleTransform(page).inverted(); + const QRect pageGeometry = it.value().first; if (pageGeometry.contains(event->position().toPoint())) { const QPointF posInPoints = screenInvTransform.map(event->position() - pageGeometry.topLeft()); d->m_linkModel.setPage(page); diff --git a/src/pdfwidgets/qpdfview_p.h b/src/pdfwidgets/qpdfview_p.h index ce9a8dba4..d349cc2ee 100644 --- a/src/pdfwidgets/qpdfview_p.h +++ b/src/pdfwidgets/qpdfview_p.h @@ -46,12 +46,12 @@ public: qreal yPositionForPage(int page) const; - QTransform screenScaleTransform() const; // points to pixels + QTransform screenScaleTransform(int page) const; // points to pixels struct DocumentLayout { QSize documentSize; - QHash<int, QRect> pageGeometries; + QHash<int, QPair<QRect, qreal>> pageGeometryAndScale; }; DocumentLayout calculateDocumentLayout() const; |