Fix: Viewport coords normalized w.r.t. full page

The coordinates in Viewport.rePos are normalized on the full page. In
two functions within pageview.cpp, these were treated as coordinates on
the cropped page.

CCBUG: 198427

This partially fixes the bug 198427 in the case that the cropping of the
target pages (and the pages around the target) is known at the time the
link is clicked. That is, it works if

- One uses 'Trim To Selection'
- One uses 'Trim To Margin' and has already viewed at the target
page(s).

In the case that the cropping of the page at the target is unknown, we
still end up at the wrong position.
remotes/origin/work/aacid/okular_focus_actions
Gerd Wachsmuth 5 years ago
parent 218c5ab64e
commit 61551d2356
  1. BIN
      autotests/data/pdf_with_internal_links.pdf
  2. 9
      autotests/data/pdf_with_internal_links.tex
  3. 44
      autotests/parttest.cpp
  4. 18
      part/pageview.cpp

@ -0,0 +1,9 @@
\documentclass{article}
\usepackage{hyperref,blindtext}
\begin{document}
\tableofcontents
\blinddocument
\end{document}

@ -107,6 +107,7 @@ private slots:
void testMouseModeMenu();
void testFullScreenRequest();
void testZoomInFacingPages();
void testLinkWithCrop();
private:
void simulateMouseSelection(double startX, double startY, double endX, double endY, QWidget *target);
@ -2110,6 +2111,49 @@ void PartTest::testZoomWithCrop()
QVERIFY(!Okular::Settings::trimMargins());
}
void PartTest::testLinkWithCrop()
{
// We test that link targets are correct with cropping, related to bug 198427
QVariantList dummyArgs;
Okular::Part part(nullptr, nullptr, dummyArgs);
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/pdf_with_internal_links.pdf")));
KActionMenu *cropMenu = part.m_pageView->findChild<KActionMenu *>(QStringLiteral("view_trim_mode"));
KToggleAction *cropAction = cropMenu->menu()->findChild<KToggleAction *>(QStringLiteral("view_trim_selection"));
part.widget()->resize(600, 400);
part.widget()->show();
QVERIFY(QTest::qWaitForWindowExposed(part.widget()));
// wait for pixmap
QTRY_VERIFY(part.m_document->page(0)->hasPixmap(part.m_pageView));
// Activate "Trim Margins"
cropAction->trigger();
const int width = part.m_pageView->viewport()->width();
const int height = part.m_pageView->viewport()->height();
const int mouseStartY = height * 0.2;
const int mouseEndY = height * 0.8;
const int mouseStartX = width * 0.2;
const int mouseEndX = width * 0.8;
// Trim the page
simulateMouseSelection(mouseStartX, mouseStartY, mouseEndX, mouseEndY, part.m_pageView->viewport());
// Click a link
const QPoint click(width * 0.2, height * 0.2);
QTest::mouseMove(part.m_pageView->viewport(), click);
QTest::mouseClick(part.m_pageView->viewport(), Qt::LeftButton, Qt::NoModifier, click);
QTRY_VERIFY2_WITH_TIMEOUT(qAbs(part.m_document->viewport().rePos.normalizedY - 0.167102333237) < 0.01, qPrintable(QString("We are at %1").arg(part.m_document->viewport().rePos.normalizedY)), 500);
// Deactivate "Trim Margins"
cropAction->trigger();
}
} // namespace Okular
int main(int argc, char *argv[])

@ -3590,13 +3590,19 @@ QPoint PageView::viewportToContentArea(const Okular::DocumentViewport &vp) const
QPoint c {r.left(), r.top()};
if (vp.rePos.enabled) {
// Convert the coordinates of vp to normalized coordinates on the cropped page.
// This is a no-op if the page isn't cropped.
const Okular::NormalizedRect &crop = d->items[vp.pageNumber]->crop();
const double normalized_on_crop_x = (vp.rePos.normalizedX - crop.left) / (crop.right - crop.left);
const double normalized_on_crop_y = (vp.rePos.normalizedY - crop.top) / (crop.bottom - crop.top);
if (vp.rePos.pos == Okular::DocumentViewport::Center) {
c.rx() += qRound(normClamp(vp.rePos.normalizedX, 0.5) * (double)r.width());
c.ry() += qRound(normClamp(vp.rePos.normalizedY, 0.0) * (double)r.height());
c.rx() += qRound(normClamp(normalized_on_crop_x, 0.5) * (double)r.width());
c.ry() += qRound(normClamp(normalized_on_crop_y, 0.0) * (double)r.height());
} else {
// TopLeft
c.rx() += qRound(normClamp(vp.rePos.normalizedX, 0.0) * (double)r.width() + viewport()->width() / 2.0);
c.ry() += qRound(normClamp(vp.rePos.normalizedY, 0.0) * (double)r.height() + viewport()->height() / 2.0);
c.rx() += qRound(normClamp(normalized_on_crop_x, 0.0) * (double)r.width() + viewport()->width() / 2.0);
c.ry() += qRound(normClamp(normalized_on_crop_y, 0.0) * (double)r.height() + viewport()->height() / 2.0);
}
} else {
// exact repositioning disabled, align page top margin with viewport top border by default
@ -4552,8 +4558,12 @@ void PageView::slotRequestVisiblePixmaps(int newValue)
nearPageNumber = i->pageNumber();
minDistance = distance;
if (geometry.height() > 0 && geometry.width() > 0) {
// Compute normalized coordinates w.r.t. cropped page
focusedX = (viewportCenterX - (double)geometry.left()) / (double)geometry.width();
focusedY = (viewportCenterY - (double)geometry.top()) / (double)geometry.height();
// Convert to normalized coordinates w.r.t. full page (no-op if not cropped)
focusedX = i->crop().left + focusedX * i->crop().width();
focusedY = i->crop().top + focusedY * i->crop().height();
}
}
}

Loading…
Cancel
Save