summaryrefslogtreecommitdiffstats
path: root/krita/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.cc
diff options
context:
space:
mode:
Diffstat (limited to 'krita/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.cc')
-rw-r--r--krita/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.cc162
1 files changed, 162 insertions, 0 deletions
diff --git a/krita/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.cc b/krita/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.cc
new file mode 100644
index 00000000..2c6562df
--- /dev/null
+++ b/krita/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.cc
@@ -0,0 +1,162 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 <cmath>
+
+#include <qapplication.h>
+
+#include <kdebug.h>
+
+#include <kis_doc.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+
+#include "kis_imagerasteredcache.h"
+
+KisImageRasteredCache::KisImageRasteredCache(KisView* view, Observer* o)
+ : m_observer(o->createNew(0, 0, 0, 0)), m_view(view)
+{
+ m_busy = false;
+ m_imageProjection = 0;
+ m_rasterSize = 64*4;
+ m_timeOutMSec = 1000;
+
+ KisImageSP img = view->canvasSubject()->currentImg();
+
+ if (!img) {
+ return;
+ }
+
+ imageSizeChanged(img->width(), img->height());
+
+ connect(img, SIGNAL(sigImageUpdated(QRect)),
+ this, SLOT(imageUpdated(QRect)));
+ connect(img, SIGNAL(sigSizeChanged(Q_INT32, Q_INT32)),
+ this, SLOT(imageSizeChanged(Q_INT32, Q_INT32)));
+ connect(&m_timer, SIGNAL(timeout()), this, SLOT(timeOut()));
+}
+
+KisImageRasteredCache::~KisImageRasteredCache() {
+ cleanUpElements();
+}
+
+void KisImageRasteredCache::imageUpdated(QRect rc) {
+
+ if (rc.isValid()) {
+ QRect r(0, 0, m_width * m_rasterSize, m_height * m_rasterSize);
+ r &= rc;
+
+ uint x = static_cast<int>(r.x() / m_rasterSize);
+ uint y = static_cast<int>(r.y() / m_rasterSize);
+ uint x2 = static_cast<int>(ceil(float(r.x() + r.width()) / float(m_rasterSize)));
+ uint y2 = static_cast<int>(ceil(float(r.y() + r.height()) / float(m_rasterSize)));
+
+ if (!m_raster.empty()) {
+ for ( ; x < x2; x++) {
+ for (uint i = y; i < y2; i++) {
+ if (x < m_raster.size()) {
+ if (i < m_raster.at(x).size()) {
+ Element* e = m_raster.at(x).at(i);
+ if (e && e->valid) {
+ e->valid = false;
+ m_queue.push_back(e);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!m_busy) {
+ // If the timer is already started, this resets it. That way, we update always
+ // m_timeOutMSec milliseconds after the lastly monitored activity
+ m_timer.start(m_timeOutMSec, true); // true->singleshot
+ }
+}
+
+void KisImageRasteredCache::imageSizeChanged(Q_INT32 w, Q_INT32 h) {
+
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+
+ cleanUpElements();
+ m_busy = false;
+
+ m_width = static_cast<int>(ceil(float(w) / float(m_rasterSize)));
+ m_height = static_cast<int>(ceil(float(h) / float(m_rasterSize)));
+
+ m_raster.resize(m_width);
+
+ int rasterX = 0;
+
+ for (int i = 0; i < m_width * m_rasterSize; i += m_rasterSize) {
+ int rasterY = 0;
+
+ m_raster.at(rasterX).resize(m_height + 1);
+
+ for (int j = 0; j < m_height * m_rasterSize; j += m_rasterSize) {
+ Element* e = new Element(m_observer->createNew(i, j, m_rasterSize, m_rasterSize));
+ m_raster.at(rasterX).at(rasterY) = e;
+ rasterY++;
+ }
+ rasterX++;
+ }
+
+ imageUpdated(QRect(0,0, image->width(), image->height()));
+}
+
+void KisImageRasteredCache::timeOut() {
+ m_busy = true;
+ KisImageSP img = m_view->canvasSubject()->currentImg();
+
+ // Temporary cache: while we are busy, we won't get the mergeImage time and again.
+ if (!m_imageProjection)
+ m_imageProjection = img->mergedImage();
+
+ // Pick one element of the cache, and update it
+ if (!m_queue.isEmpty()) {
+ m_queue.front()->observer->regionUpdated(m_imageProjection);
+ m_queue.front()->valid = true;
+ m_queue.pop_front();
+ }
+
+ // If there are still elements, we need to be called again (this emulates processEvents)
+ if (!m_queue.isEmpty()) {
+ QTimer::singleShot(0, this, SLOT(timeOut()));
+ } else {
+ emit cacheUpdated();
+ m_imageProjection = 0;
+ m_busy = false;
+ }
+}
+
+void KisImageRasteredCache::cleanUpElements() {
+ for (uint i = 0; i < m_raster.count(); i++) {
+ for (uint j = 0; j < m_raster.at(i).count(); j++) {
+ delete m_raster.at(i).at(j);
+ }
+ m_raster.at(i).clear();
+ }
+ m_raster.clear();
+ m_queue.clear();
+}
+
+#include "kis_imagerasteredcache.moc"