diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2024-03-20 21:16:11 -0700 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2024-03-22 00:17:59 -0700 |
commit | fccbc33d95c17b0911fd4cbd97998acfc8e6320f (patch) | |
tree | 2e1294947fcf43babbc81ba89bba63a4fce98c41 | |
parent | f0aa275be272c3ff8337c1d712f8833f7e5a05a6 (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.cpp | 18 | ||||
-rw-r--r-- | src/pdf/qpdfdocument_p.h | 1 | ||||
-rw-r--r-- | src/pdf/qpdfsearchmodel.cpp | 12 |
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) { |