Masterwork From Distant Lands
ActivePublic

Authored by dkazakov on May 30 2016, 2:15 PM.
diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt
index a88c7b7..b91d0c7 100644
--- a/libs/ui/CMakeLists.txt
+++ b/libs/ui/CMakeLists.txt
@@ -182,6 +182,7 @@ set(kritaui_LIB_SRCS
tool/kis_tool_freehand.cc
tool/kis_speed_smoother.cpp
tool/kis_painting_information_builder.cpp
+ tool/kis_stabilized_events_sampler.cpp
tool/kis_tool_freehand_helper.cpp
tool/kis_tool_multihand_helper.cpp
tool/kis_figure_painting_tool_helper.cpp
diff --git a/libs/ui/tests/CMakeLists.txt b/libs/ui/tests/CMakeLists.txt
index 67951c1..7219220 100644
--- a/libs/ui/tests/CMakeLists.txt
+++ b/libs/ui/tests/CMakeLists.txt
@@ -253,3 +253,9 @@ target_link_libraries(KisAnimationFrameCacheTest kritaui kritaimage ${QT_QTTEST_
set(ResourceBundleTest_SRCS ResourceBundleTest.cpp)
kde4_add_broken_unit_test(ResourceBundleTest TESTNAME krita-resourcemanager-ResourceBundleTest ${ResourceBundleTest_SRCS})
target_link_libraries(ResourceBundleTest kritaui kritalibbrush kritalibpaintop Qt5::Test )
+
+########### next target ###############
+
+set(kis_stabilized_events_sampler_test_SRCS kis_stabilized_events_sampler_test.cpp)
+kde4_add_unit_test(KisStabilizedEventsSamplerTest TESTNAME krita-ui-StabilizedEventsSamplerTest ${kis_stabilized_events_sampler_test_SRCS})
+target_link_libraries(KisStabilizedEventsSamplerTest kritaui Qt5::Test)
diff --git a/libs/ui/tests/kis_stabilized_events_sampler_test.cpp b/libs/ui/tests/kis_stabilized_events_sampler_test.cpp
new file mode 100644
index 0000000..cbd3deb
--- /dev/null
+++ b/libs/ui/tests/kis_stabilized_events_sampler_test.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2016 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * 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 "kis_stabilized_events_sampler_test.h"
+
+#include "kis_stabilized_events_sampler.h"
+#include "kis_paint_information.h"
+
+void KisStabilizedEventsSamplerTest::test()
+{
+ KisStabilizedEventsSampler sampler(20);
+
+ KisPaintInformation pi1(QPoint(10,10));
+ KisPaintInformation pi2(QPoint(20,20));
+
+ sampler.addEvent(pi1);
+
+ QTest::qSleep(50);
+
+ sampler.addEvent(pi2);
+
+ QTest::qSleep(70);
+
+ KisStabilizedEventsSampler::iterator it;
+ KisStabilizedEventsSampler::iterator end;
+ std::tie(it, end) = sampler.range();
+
+
+ int numTotal = 0;
+ int num1 = 0;
+ int num2 = 0;
+
+ for (; it != end; ++it) {
+ numTotal++;
+ if (it->pos().x() == 10) {
+ num1++;
+ } else if (it->pos().x() == 20) {
+ num2++;
+ }
+
+ qDebug() << ppVar(it->pos());
+ }
+
+ QVERIFY(numTotal >= 6);
+ QVERIFY(num1 >= 3);
+ QVERIFY(num2 >= 3);
+}
+
+QTEST_MAIN(KisStabilizedEventsSamplerTest)
diff --git a/libs/ui/tests/kis_stabilized_events_sampler_test.h b/libs/ui/tests/kis_stabilized_events_sampler_test.h
new file mode 100644
index 0000000..885ea2b
--- /dev/null
+++ b/libs/ui/tests/kis_stabilized_events_sampler_test.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * 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.
+ */
+
+#ifndef __KIS_STABILIZED_EVENTS_SAMPLER_TEST_H
+#define __KIS_STABILIZED_EVENTS_SAMPLER_TEST_H
+
+#include <QtTest/QtTest>
+
+class KisStabilizedEventsSamplerTest : public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void test();
+};
+
+#endif /* __KIS_STABILIZED_EVENTS_SAMPLER_TEST_H */
diff --git a/libs/ui/tool/kis_stabilized_events_sampler.cpp b/libs/ui/tool/kis_stabilized_events_sampler.cpp
new file mode 100644
index 0000000..c5af1eb
--- /dev/null
+++ b/libs/ui/tool/kis_stabilized_events_sampler.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * 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 "kis_stabilized_events_sampler.h"
+
+#include <QList>
+#include <QElapsedTimer>
+#include <QtMath>
+
+#include "kis_paint_information.h"
+
+
+struct KisStabilizedEventsSampler::Private
+{
+ Private(int _sampleTime) : sampleTime(_sampleTime) {}
+
+ std::function<void(const KisPaintInformation &)> paintLine;
+ QElapsedTimer lastPaintTime;
+ QList<KisPaintInformation> realEvents;
+ int sampleTime;
+
+ KisPaintInformation lastPaintInformation;
+};
+
+KisStabilizedEventsSampler::KisStabilizedEventsSampler(int sampleTime)
+ : m_d(new Private(sampleTime))
+{
+}
+
+KisStabilizedEventsSampler::~KisStabilizedEventsSampler()
+{
+}
+
+void KisStabilizedEventsSampler::setLineFunction(std::function<void(const KisPaintInformation &)> func)
+{
+ m_d->paintLine = func;
+}
+
+void KisStabilizedEventsSampler::clear()
+{
+ if (!m_d->realEvents.isEmpty()) {
+ m_d->lastPaintInformation = m_d->realEvents.last();
+ }
+
+ m_d->realEvents.clear();
+ m_d->lastPaintTime.start();
+}
+
+void KisStabilizedEventsSampler::addEvent(const KisPaintInformation &pi)
+{
+ if (!m_d->lastPaintTime.isValid()) {
+ m_d->lastPaintTime.start();
+ }
+
+ m_d->realEvents.append(pi);
+}
+
+void KisStabilizedEventsSampler::processAllEvents()
+{
+ const int elapsed = m_d->lastPaintTime.restart();
+
+ const qreal alpha = qreal(m_d->realEvents.size()) / elapsed;
+
+ for (int i = 0; i < elapsed; i += m_d->sampleTime) {
+ const int k = qFloor(alpha * i);
+
+ m_d->paintLine(m_d->realEvents[k]);
+ }
+}
+
+KisPaintInformation const& KisStabilizedEventsSampler::iterator::dereference() const
+{
+ const int k = qFloor(m_alpha * m_index);
+ return k < m_sampler->m_d->realEvents.size() ?
+ m_sampler->m_d->realEvents[k] : m_sampler->m_d->lastPaintInformation;
+}
+
+std::pair<KisStabilizedEventsSampler::iterator, KisStabilizedEventsSampler::iterator>
+KisStabilizedEventsSampler::range() const
+{
+ const int elapsed = m_d->lastPaintTime.restart() / m_d->sampleTime;
+ const qreal alpha = qreal(m_d->realEvents.size()) / elapsed;
+
+ return std::make_pair(iterator(this, 0, alpha),
+ iterator(this, elapsed, alpha));
+}
+
+
diff --git a/libs/ui/tool/kis_stabilized_events_sampler.h b/libs/ui/tool/kis_stabilized_events_sampler.h
new file mode 100644
index 0000000..f118d11
--- /dev/null
+++ b/libs/ui/tool/kis_stabilized_events_sampler.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2016 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * 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.
+ */
+
+#ifndef __KIS_STABILIZED_EVENTS_SAMPLER_H
+#define __KIS_STABILIZED_EVENTS_SAMPLER_H
+
+#include <QScopedPointer>
+
+#include <functional>
+#include <boost/iterator/iterator_facade.hpp>
+
+#include "kritaui_export.h"
+
+class KisPaintInformation;
+
+
+class KRITAUI_EXPORT KisStabilizedEventsSampler
+{
+public:
+ KisStabilizedEventsSampler(int sampleTime = 1);
+ ~KisStabilizedEventsSampler();
+
+ void setLineFunction(std::function<void(const KisPaintInformation &)> func);
+
+ void clear();
+ void addEvent(const KisPaintInformation &pi);
+ void processAllEvents();
+
+public:
+ class iterator :
+ public boost::iterator_facade <iterator,
+ KisPaintInformation const,
+ boost::forward_traversal_tag >
+ {
+ public:
+ iterator()
+ : m_sampler(0),
+ m_index(0),
+ m_alpha(0) {}
+
+ iterator(const KisStabilizedEventsSampler* sampler, int index, qreal alpha)
+ : m_sampler(sampler),
+ m_index(index),
+ m_alpha(alpha) {}
+
+ private:
+ friend class boost::iterator_core_access;
+
+ void increment() {
+ m_index++;
+ }
+
+ bool equal(iterator const& other) const {
+ return m_index == other.m_index &&
+ m_sampler == other.m_sampler;
+ }
+
+ KisPaintInformation const& dereference() const;
+
+ private:
+ const KisStabilizedEventsSampler* m_sampler;
+ int m_index;
+ qreal m_alpha;
+ };
+
+ std::pair<iterator, iterator> range() const;
+
+private:
+ struct Private;
+ const QScopedPointer<Private> m_d;
+};
+
+
+#endif /* __KIS_STABILIZED_EVENTS_SAMPLER_H */
diff --git a/libs/ui/tool/kis_tool_freehand_helper.cpp b/libs/ui/tool/kis_tool_freehand_helper.cpp
index 20d30a7..711d548 100644
--- a/libs/ui/tool/kis_tool_freehand_helper.cpp
+++ b/libs/ui/tool/kis_tool_freehand_helper.cpp
@@ -35,6 +35,7 @@
#include <brushengine/kis_paintop_utils.h>
#include "kis_update_time_monitor.h"
+#include "kis_stabilized_events_sampler.h"
#include <math.h>
@@ -77,6 +78,7 @@ struct KisToolFreehandHelper::Private
QQueue<KisPaintInformation> stabilizerDeque;
KisPaintInformation stabilizerLastPaintInfo;
QTimer stabilizerPollTimer;
+ KisStabilizedEventsSampler stabilizedSampler;
int canvasRotation;
bool canvasMirroredH;
@@ -517,6 +519,7 @@ void KisToolFreehandHelper::paint(KoPointerEvent *event)
if (m_d->smoothingOptions->smoothingType() == KisSmoothingOptions::STABILIZER) {
m_d->stabilizerLastPaintInfo = info;
+ m_d->stabilizedSampler.addEvent(info);
} else {
m_d->previousPaintInformation = info;
}
@@ -604,8 +607,10 @@ void KisToolFreehandHelper::stabilizerStart(KisPaintInformation firstPaintInfo)
m_d->stabilizerLastPaintInfo = firstPaintInfo;
// Poll and draw each millisecond
- m_d->stabilizerPollTimer.setInterval(1);
+ m_d->stabilizerPollTimer.setInterval(50);
m_d->stabilizerPollTimer.start();
+
+ m_d->stabilizedSampler.clear();
}
KisPaintInformation
@@ -646,9 +651,6 @@ KisToolFreehandHelper::Private::getStabilizedPaintInfo(const QQueue<KisPaintInfo
void KisToolFreehandHelper::stabilizerPollAndPaint()
{
- KisPaintInformation newInfo =
- m_d->getStabilizedPaintInfo(m_d->stabilizerDeque, m_d->stabilizerLastPaintInfo);
-
bool canPaint = true;
if (m_d->smoothingOptions->useDelayDistance()) {
@@ -662,15 +664,25 @@ void KisToolFreehandHelper::stabilizerPollAndPaint()
}
if (canPaint) {
- paintLine(m_d->previousPaintInformation, newInfo);
- m_d->previousPaintInformation = newInfo;
+ KisStabilizedEventsSampler::iterator it;
+ KisStabilizedEventsSampler::iterator end;
+ std::tie(it, end) = m_d->stabilizedSampler.range();
- // Push the new entry through the queue
- m_d->stabilizerDeque.dequeue();
- m_d->stabilizerDeque.enqueue(m_d->stabilizerLastPaintInfo);
+ for (; it != end; ++it) {
+ KisPaintInformation sampledInfo = *it;
- emit requestExplicitUpdateOutline();
+ KisPaintInformation newInfo =
+ m_d->getStabilizedPaintInfo(m_d->stabilizerDeque, sampledInfo);
+
+ paintLine(m_d->previousPaintInformation, newInfo);
+ m_d->previousPaintInformation = newInfo;
+ // Push the new entry through the queue
+ m_d->stabilizerDeque.dequeue();
+ m_d->stabilizerDeque.enqueue(sampledInfo);
+ }
+
+ emit requestExplicitUpdateOutline();
} else if (m_d->stabilizerDeque.head().pos() != m_d->previousPaintInformation.pos()) {
QQueue<KisPaintInformation>::iterator it = m_d->stabilizerDeque.begin();
@@ -681,6 +693,8 @@ void KisToolFreehandHelper::stabilizerPollAndPaint()
++it;
}
}
+
+ m_d->stabilizedSampler.clear();
}
void KisToolFreehandHelper::stabilizerEnd()
dkazakov edited the content of this paste. (Show Details)May 30 2016, 2:15 PM
dkazakov changed the title of this paste from untitled to Masterwork From Distant Lands.