summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2024-03-20 21:16:11 -0700
committerShawn Rutledge <shawn.rutledge@qt.io>2024-03-22 00:17:59 -0700
commitfccbc33d95c17b0911fd4cbd97998acfc8e6320f (patch)
tree2e1294947fcf43babbc81ba89bba63a4fce98c41
parentf0aa275be272c3ff8337c1d712f8833f7e5a05a6 (diff)
Convert search result bounds to account for PDF transforms
As a drive-by, remove unneeded includes. QPdfDocumentPrivate::convertPageRect() will be useful for fixing related bugs. If PDF files can contain arbitrary transforms, and "page coordinates" returned from pdfium functions are not already converted, then it's never ok to just subtract from page height to invert the y's. Pick-to: 6.5 6.6 6.7 Fixes: QTBUG-120764 Change-Id: Iffce528c0c5e66c499e7147078b7b8718f7610ce Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
-rw-r--r--src/pdf/qpdfdocument.cpp18
-rw-r--r--src/pdf/qpdfdocument_p.h1
-rw-r--r--src/pdf/qpdfsearchmodel.cpp12
3 files changed, 26 insertions, 5 deletions
diff --git a/src/pdf/qpdfdocument.cpp b/src/pdf/qpdfdocument.cpp
index 6de2fbc6c..11d886dc4 100644
--- a/src/pdf/qpdfdocument.cpp
+++ b/src/pdf/qpdfdocument.cpp
@@ -474,6 +474,24 @@ QRectF QPdfDocumentPrivate::getCharBox(FPDF_TEXTPAGE textPage, double pageHeight
return QRectF(l, pageHeight - t, r - l, t - b);
}
+/*! \internal
+ Convert the bounding box defined by \a left \a top \a right and \a bottom
+ to the usual 1x (pixels = points) 4th-quadrant "view" coordinate system
+ that we use for rendering things on top of the page image.
+ Some PDF files have internal transforms that make this coordinate
+ system different from "page coordinates", so we cannot just
+ subtract from page height to invert the y coordinates, in general.
+ */
+QRectF QPdfDocumentPrivate::mapPageToView(FPDF_PAGE pdfPage, double left, double top, double right, double bottom)
+{
+ const auto pageHeight = FPDF_GetPageHeight(pdfPage);
+ const auto pageWidth = FPDF_GetPageWidth(pdfPage);
+ int xfmLeft, xfmTop, xfmRight, xfmBottom;
+ FPDF_PageToDevice(pdfPage, 0, 0, qRound(pageWidth), qRound(pageHeight), 0, left, top, &xfmLeft, &xfmTop);
+ FPDF_PageToDevice(pdfPage, 0, 0, qRound(pageWidth), qRound(pageHeight), 0, right, bottom, &xfmRight, &xfmBottom);
+ return QRectF(xfmLeft, xfmTop, xfmRight - xfmLeft, xfmBottom - xfmTop);
+}
+
QPdfDocumentPrivate::TextPosition QPdfDocumentPrivate::hitTest(int page, QPointF position)
{
const QPdfMutexLocker lock;
diff --git a/src/pdf/qpdfdocument_p.h b/src/pdf/qpdfdocument_p.h
index 088c570d1..29ca9e2e3 100644
--- a/src/pdf/qpdfdocument_p.h
+++ b/src/pdf/qpdfdocument_p.h
@@ -81,6 +81,7 @@ public:
QString getText(FPDF_TEXTPAGE textPage, int startIndex, int count);
QPointF getCharPosition(FPDF_TEXTPAGE textPage, double pageHeight, int charIndex);
QRectF getCharBox(FPDF_TEXTPAGE textPage, double pageHeight, int charIndex);
+ QRectF mapPageToView(FPDF_PAGE pdfPage, double left, double top, double right, double bottom);
// FPDF takes the rotation parameter as an int.
// This enum is mapping the int values defined in fpdfview.h:956.
diff --git a/src/pdf/qpdfsearchmodel.cpp b/src/pdf/qpdfsearchmodel.cpp
index 8a997c84e..a81ae77dc 100644
--- a/src/pdf/qpdfsearchmodel.cpp
+++ b/src/pdf/qpdfsearchmodel.cpp
@@ -3,12 +3,11 @@
#include "qpdfdocument_p.h"
#include "qpdflink.h"
-#include "qpdflink_p.h"
#include "qpdfsearchmodel.h"
#include "qpdfsearchmodel_p.h"
-#include "third_party/pdfium/public/fpdf_doc.h"
#include "third_party/pdfium/public/fpdf_text.h"
+#include "third_party/pdfium/public/fpdfview.h"
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qloggingcategory.h>
@@ -265,7 +264,6 @@ bool QPdfSearchModelPrivate::doSearch(int page)
qWarning() << "failed to load page" << page;
return false;
}
- double pageHeight = FPDF_GetPageHeight(pdfPage);
FPDF_TEXTPAGE textPage = FPDFText_LoadPage(pdfPage);
if (!textPage) {
qWarning() << "failed to load text of page" << page;
@@ -283,9 +281,12 @@ bool QPdfSearchModelPrivate::doSearch(int page)
int startIndex = -1;
int endIndex = -1;
for (int r = 0; r < rectCount; ++r) {
+ // get bounding box of search result in page coordinates
double left, top, right, bottom;
FPDFText_GetRect(textPage, r, &left, &top, &right, &bottom);
- rects << QRectF(left, pageHeight - top, right - left, top - bottom);
+ // deal with any internal PDF transforms and
+ // convert to the 1x (pixels = points) 4th-quadrant coordinate system
+ rects << document->d->mapPageToView(pdfPage, left, top, right, bottom);
if (r == 0) {
startIndex = FPDFText_GetCharIndexAtPos(textPage, left, top,
CharacterHitTolerance, CharacterHitTolerance);
@@ -294,7 +295,8 @@ bool QPdfSearchModelPrivate::doSearch(int page)
endIndex = FPDFText_GetCharIndexAtPos(textPage, right, top,
CharacterHitTolerance, CharacterHitTolerance);
}
- qCDebug(qLcS) << rects.last() << "char idx" << startIndex << "->" << endIndex;
+ qCDebug(qLcS) << rects.last() << "char idx" << startIndex << "->" << endIndex
+ << "from page rect" << left << top << right << bottom;
}
QString contextBefore, contextAfter;
if (startIndex >= 0 || endIndex >= 0) {