From 9b9734ffd11b9601d1b17e1e9c4b191dc5b395c9 Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Sun, 13 Dec 2020 16:19:59 +0100 Subject: [PATCH] Bugfix: Text selection --- PdfForQtLib/sources/pdftextlayout.cpp | 38 +++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/PdfForQtLib/sources/pdftextlayout.cpp b/PdfForQtLib/sources/pdftextlayout.cpp index 0ae3d80..3dd5aa2 100644 --- a/PdfForQtLib/sources/pdftextlayout.cpp +++ b/PdfForQtLib/sources/pdftextlayout.cpp @@ -338,12 +338,16 @@ PDFTextSelection PDFTextLayout::createTextSelection(PDFInteger pageIndex, const QRectF rect(xMin, yMin, xMax - xMin, yMax - yMin); QPainterPath rectPath; rectPath.addRect(rect); - QPainterPath intersectionPath = block.getBoundingBox().intersected(rectPath); + const QPainterPath& boundingBoxPath = block.getBoundingBox(); + QPainterPath intersectionPath = boundingBoxPath.intersected(rectPath); if (!intersectionPath.isEmpty()) { QRectF intersectionRect = intersectionPath.boundingRect(); Q_ASSERT(intersectionRect.isValid()); + bool isTopPointAboveText = false; + bool isBottomPointBelowText = false; + const PDFTextLines& lines = block.getLines(); auto itLineA = std::find_if(lines.cbegin(), lines.cend(), [pointA](const PDFTextLine& line) { return line.getBoundingBox().contains(pointA); }); auto itLineB = std::find_if(lines.cbegin(), lines.cend(), [pointB](const PDFTextLine& line) { return line.getBoundingBox().contains(pointB); }); @@ -361,10 +365,24 @@ PDFTextSelection PDFTextLayout::createTextSelection(PDFInteger pageIndex, const { // Otherwise points are not in the same line. Then start point will be // point top of the second point. Bottom point will mark end of selection. - if (pointA.y() > pointB.y()) + if (pointA.y() < pointB.y()) { std::swap(pointA, pointB); } + + QRectF rect = boundingBoxPath.controlPointRect(); + + // If start point is above the text block, move start point to the left. + if (rect.bottom() < pointA.y()) + { + pointA.setX(rect.left()); + isTopPointAboveText = true; + } + if (rect.top() > pointB.y()) + { + pointB.setX(rect.right()); + isBottomPointBelowText = true; + } } // Now, we have pointA as start point and pointB as end point. We must found @@ -409,6 +427,22 @@ PDFTextSelection PDFTextLayout::createTextSelection(PDFInteger pageIndex, const } } + if (isTopPointAboveText && !lines.empty()) + { + ptrA.pageIndex = pageIndex; + ptrA.blockIndex = blockId; + ptrA.lineIndex = 0; + ptrA.characterIndex = 0; + } + + if (isBottomPointBelowText && !lines.empty()) + { + ptrB.pageIndex = pageIndex; + ptrB.blockIndex = blockId; + ptrB.lineIndex = lines.size() - 1; + ptrB.characterIndex = lines.back().getCharacters().size() - 1; + } + // If we have filled the pointers, add them to the selection if (ptrA.isValid() && ptrB.isValid()) {