[graphics/krita] libs/ui: Implement a GUI option for Brush Speed Smoothness

Dmitry Kazakov null at kde.org
Thu Sep 16 13:03:05 BST 2021


Git commit d72db16294a7f0415e9d592594b7e2cfedacf0ba by Dmitry Kazakov.
Committed on 11/09/2021 at 09:00.
Pushed by dkazakov into branch 'master'.

Implement a GUI option for Brush Speed Smoothness

When we calculate the stylus speed we need to smooth values
a bit. Previuosly, Krita users expected rather huge amount of
smoothness, but now the default value is very low. If the user
want to make it larger, he/she is free to do that in the settings.
No restart is needed.

"Brush Speed Smoothness" value technically means how many hardware
samples we are going to average. It means that the value might have
different effect on different tablets, OSes and tablet APIs.

CC:kimageshop at kde.org

M  +7    -0    libs/ui/dialogs/kis_dlg_preferences.cc
M  +15   -2    libs/ui/forms/wdgtabletsettings.ui
M  +5    -17   libs/ui/tool/kis_painting_information_builder.cpp
M  +0    -1    libs/ui/tool/kis_painting_information_builder.h
M  +16   -6    libs/ui/tool/kis_speed_smoother.cpp
M  +2    -1    libs/ui/tool/kis_speed_smoother.h

https://invent.kde.org/graphics/krita/commit/d72db16294a7f0415e9d592594b7e2cfedacf0ba

diff --git a/libs/ui/dialogs/kis_dlg_preferences.cc b/libs/ui/dialogs/kis_dlg_preferences.cc
index 03e35ebf26..54d8039e3b 100644
--- a/libs/ui/dialogs/kis_dlg_preferences.cc
+++ b/libs/ui/dialogs/kis_dlg_preferences.cc
@@ -877,6 +877,7 @@ void TabletSettingsTab::setDefault()
 
     m_page->chkUseTimestampsForBrushSpeed->setChecked(false);
     m_page->intMaxAllowedBrushSpeed->setValue(30);
+    m_page->intBrushSpeedSmoothing->setValue(3);
 
 }
 
@@ -939,6 +940,11 @@ TabletSettingsTab::TabletSettingsTab(QWidget* parent, const char* name): QWidget
     m_page->intMaxAllowedBrushSpeed->setSuffix(" px/ms");
     m_page->intMaxAllowedBrushSpeed->setRange(1, 100);
     m_page->intMaxAllowedBrushSpeed->setValue(cfg.readEntry("maxAllowedSpeedValue", 30));
+
+    m_page->intBrushSpeedSmoothing->setPrefix("Stylus speed smoothing: ");
+    m_page->intBrushSpeedSmoothing->setSuffix(" samples");
+    m_page->intBrushSpeedSmoothing->setRange(3, 100);
+    m_page->intBrushSpeedSmoothing->setValue(cfg.readEntry("speedValueSmoothing", 3));
 }
 
 void TabletSettingsTab::slotTabletTest()
@@ -1991,6 +1997,7 @@ bool KisDlgPreferences::editPreferences()
 #endif
         cfg.writeEntry<bool>("useTimestampsForBrushSpeed", m_tabletSettings->m_page->chkUseTimestampsForBrushSpeed->isChecked());
         cfg.writeEntry<int>("maxAllowedSpeedValue", m_tabletSettings->m_page->intMaxAllowedBrushSpeed->value());
+        cfg.writeEntry<int>("speedValueSmoothing", m_tabletSettings->m_page->intBrushSpeedSmoothing->value());
 
         m_performanceSettings->save();
 
diff --git a/libs/ui/forms/wdgtabletsettings.ui b/libs/ui/forms/wdgtabletsettings.ui
index ef86cad21f..e2edf1c621 100644
--- a/libs/ui/forms/wdgtabletsettings.ui
+++ b/libs/ui/forms/wdgtabletsettings.ui
@@ -10,8 +10,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>639</width>
-    <height>564</height>
+    <width>648</width>
+    <height>588</height>
    </rect>
   </property>
   <property name="sizePolicy">
@@ -233,6 +233,19 @@
      </property>
     </widget>
    </item>
+   <item>
+    <widget class="KisSliderSpinBox" name="intBrushSpeedSmoothing" native="true">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="toolTip">
+      <string>Amount of smoothing Krita should do to speed sensor. This value is very hardware-dependent.</string>
+     </property>
+    </widget>
+   </item>
    <item>
     <widget class="QPushButton" name="btnTabletTest">
      <property name="text">
diff --git a/libs/ui/tool/kis_painting_information_builder.cpp b/libs/ui/tool/kis_painting_information_builder.cpp
index 45cb98cb74..34ebe0a933 100644
--- a/libs/ui/tool/kis_painting_information_builder.cpp
+++ b/libs/ui/tool/kis_painting_information_builder.cpp
@@ -47,7 +47,7 @@ void KisPaintingInformationBuilder::updateSettings()
     KisCubicCurve curve;
     curve.fromString(cfg.pressureTabletCurve());
     m_pressureSamples = curve.floatTransfer(LEVEL_OF_PRESSURE_RESOLUTION + 1);
-    m_useTimestamps = cfg.readEntry("useTimestampsForBrushSpeed", false);
+    m_speedSmoother->updateSettings();
 }
 
 KisPaintInformation KisPaintingInformationBuilder::startStroke(KoPointerEvent *event,
@@ -112,12 +112,7 @@ KisPaintInformation KisPaintingInformationBuilder::createPaintingInformation(KoP
     QPointF adjusted = adjustDocumentPoint(event->point, m_startPoint);
     QPointF imagePoint = documentToImage(adjusted);
     qreal perspective = calculatePerspective(adjusted);
-    qreal speed;
-    if (m_useTimestamps) {
-        speed = m_speedSmoother->getNextSpeed(imageToView(imagePoint), event->time());
-    } else {
-        speed = m_speedSmoother->getNextSpeed(imageToView(imagePoint));
-    }
+    const qreal speed = m_speedSmoother->getNextSpeed(imageToView(imagePoint), event->time());
 
     KisPaintInformation pi(imagePoint,
                            !m_pressureDisabled ? 1.0 : pressureToCurve(event->pressure()),
@@ -140,17 +135,10 @@ KisPaintInformation KisPaintingInformationBuilder::hover(const QPointF &imagePoi
                                                          bool isStrokeStarted)
 {
     qreal perspective = calculatePerspective(imagePoint);
-    qreal speed;
-    if (m_useTimestamps) {
-        speed = !isStrokeStarted && event ?
-                m_speedSmoother->getNextSpeed(imageToView(imagePoint), event->time()) :
-                m_speedSmoother->lastSpeed();
-    } else {
-        speed = !isStrokeStarted ?
-                m_speedSmoother->getNextSpeed(imageToView(imagePoint)) :
-                m_speedSmoother->lastSpeed();
-    }
 
+    const qreal speed = !isStrokeStarted && event ?
+        m_speedSmoother->getNextSpeed(imageToView(imagePoint), event->time()) :
+        m_speedSmoother->lastSpeed();
 
     if (event) {
         return KisPaintInformation::createHoveringModeInfo(imagePoint,
diff --git a/libs/ui/tool/kis_painting_information_builder.h b/libs/ui/tool/kis_painting_information_builder.h
index d70a766da1..e4740d628f 100644
--- a/libs/ui/tool/kis_painting_information_builder.h
+++ b/libs/ui/tool/kis_painting_information_builder.h
@@ -70,7 +70,6 @@ private:
     QPointF m_startPoint;
     QScopedPointer<KisSpeedSmoother> m_speedSmoother;
     bool m_pressureDisabled;
-    bool m_useTimestamps;
 };
 
 class KRITAUI_EXPORT KisConverterPaintingInformationBuilder : public KisPaintingInformationBuilder
diff --git a/libs/ui/tool/kis_speed_smoother.cpp b/libs/ui/tool/kis_speed_smoother.cpp
index a4ecfdc17c..26b8da632c 100644
--- a/libs/ui/tool/kis_speed_smoother.cpp
+++ b/libs/ui/tool/kis_speed_smoother.cpp
@@ -59,6 +59,9 @@ struct KisSpeedSmoother::Private
     qreal lastTime;
     qreal lastSpeed;
 
+    bool useTimestamps = false;
+    int numSmoothingSamples = 3;
+
     accumulator_set<qreal, stats<tag::rolling_mean>> timeDiffAccumulator;
 
 };
@@ -67,6 +70,7 @@ struct KisSpeedSmoother::Private
 KisSpeedSmoother::KisSpeedSmoother()
     : m_d(new Private(MAX_SMOOTH_HISTORY))
 {
+    updateSettings();
 }
 
 KisSpeedSmoother::~KisSpeedSmoother()
@@ -80,12 +84,10 @@ qreal KisSpeedSmoother::lastSpeed() const
 
 qreal KisSpeedSmoother::getNextSpeed(const QPointF &pt, ulong timestamp)
 {
-    return getNextSpeedImpl(pt, timestamp);
-}
+    const qreal time = m_d->useTimestamps ?
+        qreal(timestamp) :
+        qreal(m_d->timer.nsecsElapsed()) / 1000000;
 
-qreal KisSpeedSmoother::getNextSpeed(const QPointF &pt)
-{
-    const qreal time = qreal(m_d->timer.nsecsElapsed()) / 1000000;
     return getNextSpeedImpl(pt, time);
 }
 
@@ -98,6 +100,14 @@ void KisSpeedSmoother::clear()
     m_d->lastSpeed = 0.0;
 }
 
+void KisSpeedSmoother::updateSettings()
+{
+
+    KisConfig cfg(true);
+    m_d->useTimestamps = cfg.readEntry("useTimestampsForBrushSpeed", false);
+    m_d->numSmoothingSamples = cfg.readEntry("speedValueSmoothing", 3);
+}
+
 qreal KisSpeedSmoother::getNextSpeedImpl(const QPointF &pt, qreal time)
 {
     const qreal dist = kisDistance(pt, m_d->lastPoint);
@@ -138,7 +148,7 @@ qreal KisSpeedSmoother::getNextSpeedImpl(const QPointF &pt, qreal time)
         totalDistance += it->distance;
         totalTime += avgTimeDiff;
 
-        if (itemsSearched > NUM_SMOOTHING_SAMPLES &&
+        if (itemsSearched > m_d->numSmoothingSamples &&
             totalDistance > MIN_TRACKING_DISTANCE) {
 
             break;
diff --git a/libs/ui/tool/kis_speed_smoother.h b/libs/ui/tool/kis_speed_smoother.h
index 936a53da0f..f99931c007 100644
--- a/libs/ui/tool/kis_speed_smoother.h
+++ b/libs/ui/tool/kis_speed_smoother.h
@@ -20,9 +20,10 @@ public:
 
     qreal lastSpeed() const;
     qreal getNextSpeed(const QPointF &pt, ulong timestamp);
-    qreal getNextSpeed(const QPointF &pt);
     void clear();
 
+    void updateSettings();
+
 private:
     qreal getNextSpeedImpl(const QPointF &pt, qreal time);
 private:



More information about the kimageshop mailing list