diff --git a/pdf/pdfcanvas.cpp b/pdf/pdfcanvas.cpp index c2fea683..d9ff2170 100644 --- a/pdf/pdfcanvas.cpp +++ b/pdf/pdfcanvas.cpp @@ -797,3 +797,54 @@ QPair PDFCanvas::pageAtPoint(const QPointF &point) const } return QPair{-1, QRectF()}; } + +class PDFCanvas::PageIterator::Private { +public: + Private(PDFCanvas *canvas): parent(canvas), i(0) + { + } + + PDFCanvas *parent; + int i; + PDFPage &page; + QRectF visibleArea; +}; + +class PDFCanvas::PageIterator { +public: + PageIterator(): d(new Private(nullptr)) + { + } + ~PageIterator() + { + delete d; + } + bool next() + { + if (!parent || d->i >= parent->d->pageCount) + return false; + + d->page = parent->d->pages.value(d->i); + d->i += 1; + return true; + } + bool visible() + { + + } +}; + +bool PDFCanvas::begin(PDFCanvas::PageIterator &it) +{ + if (d->pageCount == 0 || !d->flickable) + return false; + + delete(it.d->parent); + it.d->parent = this; + it.d->i = 0; + it.d->visibleArea.set(d->flickable->property("contentX").toFloat(), + d->flickable->property("contentY").toFloat(), + d->flickable->width(), d->flickable->height()); + + return it.next(); +} diff --git a/pdf/pdfcanvas.h b/pdf/pdfcanvas.h index b6a0ddf6..169ff270 100644 --- a/pdf/pdfcanvas.h +++ b/pdf/pdfcanvas.h @@ -43,6 +43,17 @@ class PDFCanvas : public QQuickItem typedef QPair ReducedBox; + class PageIterator { + public: + ~PageIterator(); + + bool next(); + bool visible(); + private: + class Private; + Private * const d; + }; + Q_INVOKABLE QRectF pageRectangle(int index) const; QQuickItem *flickable() const; @@ -86,6 +97,7 @@ class PDFCanvas : public QQuickItem int currentPage() const; void layout(); + bool begin(PageIterator &it); /** * \return The url of the link at point or an empty url if there is no link at point. diff --git a/pdf/pdfobserver.cpp b/pdf/pdfobserver.cpp new file mode 100644 index 00000000..f6220b48 --- /dev/null +++ b/pdf/pdfobserver.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2017 Caliste Damien. + * Contact: Damien Caliste + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "pdfobserver.h" + +PDFObserver::PDFObserver(QQuickItem *parent) + : QQuickItem(parent), m_active(false) +{ +} + +PDFObserver::~PDFObserver() +{ +} + +bool PDFObserver::active() const +{ + return m_active; +} + +void PDFObserver::setActive(bool value) +{ + if (value == m_active) + return; + + m_active = value; + emit activeChanged(); + + if (m_active) + update(); +} + +void PDFObserver::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + if (m_active) + update(); +} + +QSGNode* PDFObserver::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *) +{ + if (!m_active) + return nullptr; + + QSGNode *root = static_cast(node); + if (!root) { + root = new QSGNode; + } + + for (int i = 0; i < d->pageCount; ++i) { + PDFPage &page = d->pages[i]; + + QSGTransformNode *t = static_cast(root->childAtIndex(i)); + if (!t) { + t = new QSGTransformNode; + t->setFlag(QSGNode::OwnedByParent); + root->appendChildNode(t); + } + + QMatrix4x4 m; + m.translate(0, page.rect.y()); + t->setMatrix(m); + + if (showPage) { + QRectF inter = page.rect.intersected(visibleArea); + qreal area = inter.width() * inter.height(); + // Select the current page as the page with the maximum + // visible area. + if (area > maxVisibleArea) { + maxVisibleArea = area; + currentPage = i + 1; + } + } + + if (showPage) { + // Node hierachy: + // t + // |-bg + // | |-tn + // | | |- patch1... + // | |-n + // | | |- link1 + // | | |- link2... + QSGSimpleRectNode *bg = static_cast(t->firstChild()); + if (!bg) { + bg = new QSGSimpleRectNode; + bg->setFlag(QSGNode::OwnedByParent); + bg->setColor(d->pagePlaceholderColor); + t->appendChildNode(bg); + } + bg->setRect(0., 0., page.rect.width(), page.rect.height()); + + if (page.texture) { + QSGSimpleTextureNode *tn = static_cast(bg->firstChild()); + if (!tn) { + tn = new QSGSimpleTextureNode; + tn->setFlag(QSGNode::OwnedByParent); + bg->appendChildNode(tn); + } + putTexture(tn, width(), page.renderWidth, page.textureArea, page.texture); + + if (!page.patches.empty()) { + QSGSimpleTextureNode *ptn = static_cast(tn->firstChild()); + for (QList::iterator it = page.patches.begin(); + it != page.patches.end(); it++) { + if (!ptn) { + ptn = new QSGSimpleTextureNode; + ptn->setFlag(QSGNode::OwnedByParent); + tn->appendChildNode(ptn); + } + + putTexture(ptn, width(), page.renderWidth, it->first, it->second); + + ptn = static_cast(ptn->nextSibling()); + } + } else { + // Delete all previously registered patches. + for (QSGNode *child = tn->firstChild(); child; child = tn->firstChild()) + delete child; + } + } else { + delete bg->firstChild(); // delete the texture root here. + } + } else { + delete t->firstChild(); + } + } + + return root; +} diff --git a/pdf/pdfobserver.h b/pdf/pdfobserver.h new file mode 100644 index 00000000..4b3ae285 --- /dev/null +++ b/pdf/pdfobserver.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2017 Caliste Damien. + * Contact: Damien Caliste + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PDFOBSERVER_H +#define PDFOBSERVER_H + +#include + +class PDFObserver : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) + +public: + PDFObserver(QQuickItem *parent = 0); + ~PDFObserver(); + + bool active() const; + void setActive(bool value); + +signals: + void activeChanged(); + +protected: + virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); + virtual QSGNode* updatePaintNode(QSGNode *node, UpdatePaintNodeData*); + +private: + bool m_active; +}; + +Q_DECLARE_METATYPE(PDFObserver*) + +#endif // PDFOBSERVER_H