File indexing completed on 2024-04-28 15:51:45

0001 /*
0002     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0003 
0004 */
0005 
0006 #include "magnifierview.h"
0007 
0008 #include <QPainter>
0009 
0010 #include "core/document.h"
0011 #include "core/generator.h"
0012 #include "gui/pagepainter.h"
0013 #include "gui/priorities.h"
0014 
0015 static const int SCALE = 10;
0016 
0017 MagnifierView::MagnifierView(Okular::Document *document, QWidget *parent)
0018     : QWidget(parent)
0019     , m_document(document)
0020     , m_page(nullptr)
0021 {
0022     document->addObserver(this);
0023 }
0024 
0025 MagnifierView::~MagnifierView()
0026 {
0027     m_document->removeObserver(this);
0028 }
0029 
0030 void MagnifierView::notifySetup(const QVector<Okular::Page *> &pages, int setupFlags)
0031 {
0032     if (!(setupFlags & Okular::DocumentObserver::DocumentChanged)) {
0033         return;
0034     }
0035 
0036     m_pages = pages;
0037     m_page = nullptr;
0038     m_current = -1;
0039 }
0040 
0041 void MagnifierView::notifyPageChanged(int page, int flags)
0042 {
0043     Q_UNUSED(page);
0044     Q_UNUSED(flags);
0045 
0046     if (isVisible()) {
0047         update();
0048     }
0049 }
0050 
0051 bool MagnifierView::canUnloadPixmap(int page) const
0052 {
0053     return (page != m_current);
0054 }
0055 
0056 void MagnifierView::notifyCurrentPageChanged(int previous, int current)
0057 {
0058     Q_UNUSED(previous);
0059 
0060     if (current != m_current) {
0061         m_current = current;
0062         m_page = m_pages[current];
0063 
0064         if (isVisible()) {
0065             requestPixmap();
0066             update();
0067         }
0068     }
0069 }
0070 
0071 void MagnifierView::updateView(const Okular::NormalizedPoint &p, const Okular::Page *page)
0072 {
0073     m_viewpoint = p;
0074 
0075     if (page != m_page) // ok, we are screwed
0076     {
0077         m_page = page;
0078         m_current = page->number();
0079     }
0080 
0081     if (isVisible()) {
0082         requestPixmap();
0083         update();
0084     }
0085 }
0086 
0087 void MagnifierView::paintEvent(QPaintEvent *e)
0088 {
0089     Q_UNUSED(e);
0090 
0091     QPainter p(this);
0092 
0093     if (m_page) {
0094         QRect where = QRect(0, 0, width(), height());
0095         PagePainter::paintCroppedPageOnPainter(&p, m_page, this, 0, m_page->width() * SCALE, m_page->height() * SCALE, where, normalizedView(), nullptr);
0096     }
0097 
0098     drawTicks(&p);
0099 }
0100 
0101 void MagnifierView::move(int x, int y)
0102 {
0103     QWidget::move(x, y);
0104     requestPixmap();
0105 }
0106 
0107 void MagnifierView::requestPixmap()
0108 {
0109     if (!m_page) {
0110         return;
0111     }
0112     const int full_width = m_page->width() * SCALE;
0113     const int full_height = m_page->height() * SCALE;
0114 
0115     Okular::NormalizedRect nrect = normalizedView();
0116 
0117     if (!m_page->hasPixmap(this, full_width, full_height, nrect)) {
0118         Okular::PixmapRequest *p = new Okular::PixmapRequest(this, m_current, full_width, full_height, devicePixelRatioF(), PAGEVIEW_PRIO, Okular::PixmapRequest::Asynchronous);
0119 
0120         if (m_page->hasTilesManager(this)) {
0121             p->setTile(true);
0122         }
0123 
0124         // request a little bit bigger rectangle then currently viewed, but not the full scale page
0125         const double rect_width = (nrect.right - nrect.left) * 0.5, rect_height = (nrect.bottom - nrect.top) * 0.5;
0126 
0127         const double top = qMax(nrect.top - rect_height, 0.0);
0128         const double bottom = qMin(nrect.bottom + rect_height, 1.0);
0129         const double left = qMax(nrect.left - rect_width, 0.0);
0130         const double right = qMin(nrect.right + rect_width, 1.0);
0131 
0132         p->setNormalizedRect(Okular::NormalizedRect(left, top, right, bottom));
0133 
0134         m_document->requestPixmaps({p});
0135     }
0136 }
0137 
0138 Okular::NormalizedRect MagnifierView::normalizedView() const
0139 {
0140     double h = (double)height() / (SCALE * m_page->height() * 2);
0141     double w = (double)width() / (SCALE * m_page->width() * 2);
0142     return Okular::NormalizedRect(m_viewpoint.x - w, m_viewpoint.y - h, m_viewpoint.x + w, m_viewpoint.y + h);
0143 }
0144 
0145 void MagnifierView::drawTicks(QPainter *p)
0146 {
0147     p->save();
0148 
0149     p->setPen(QPen(Qt::black, 0));
0150     // the cross
0151     p->drawLine(width() / 2, 0, width() / 2, height() - 1);
0152     p->drawLine(0, height() / 2, width() - 1, height() / 2);
0153 
0154     // the borders
0155     p->drawLine(0, 0, width() - 1, 0);
0156     p->drawLine(width() - 1, 0, width() - 1, height() - 1);
0157     p->drawLine(0, height() - 1, width() - 1, height() - 1);
0158     p->drawLine(0, height() - 1, 0, 0);
0159 
0160     // ticks
0161     // TODO possibility to switch units (pt, mm, cc, in, printing dots)
0162     float ps = (float)SCALE * 5; // how much pixels in widget is one pixel in document * how often
0163     int tw = 10;                 // tick size in pixels
0164 
0165     for (float x = 0; x < width(); x += ps) {
0166         p->drawLine(x, 1, x, tw);
0167         p->drawLine(x, height() - 1, x, height() - tw - 1);
0168         p->drawLine(1, x, tw, x);
0169         p->drawLine(width() - 1, x, width() - tw - 1, x);
0170     }
0171 
0172     p->restore();
0173 }
0174 
0175 #include "moc_magnifierview.cpp"