diff --git a/libs/ui/kis_config.h b/libs/ui/kis_config.h --- a/libs/ui/kis_config.h +++ b/libs/ui/kis_config.h @@ -498,8 +498,8 @@ int stabilizerSampleSize(bool defaultValue = false) const; void setStabilizerSampleSize(int value); - int stabilizerDelayedPaintInterval(bool defaultValue = false) const; - void setStabilizerDelayedPaintInterval(int value); + bool stabilizerDelayedPaint(bool defaultValue = false) const; + void setStabilizerDelayedPaint(bool value); QString customFFMpegPath(bool defaultValue = false) const; void setCustomFFMpegPath(const QString &value) const; diff --git a/libs/ui/kis_config.cc b/libs/ui/kis_config.cc --- a/libs/ui/kis_config.cc +++ b/libs/ui/kis_config.cc @@ -1747,17 +1747,17 @@ m_cfg.writeEntry("stabilizerSampleSize", value); } -int KisConfig::stabilizerDelayedPaintInterval(bool defaultValue) const +bool KisConfig::stabilizerDelayedPaint(bool defaultValue) const { - const int defaultInterval = 20; + const bool defaultEnabled = true; return defaultValue ? - defaultInterval : m_cfg.readEntry("stabilizerDelayedPaintInterval", defaultInterval); + defaultEnabled : m_cfg.readEntry("stabilizerDelayedPaint", defaultEnabled); } -void KisConfig::setStabilizerDelayedPaintInterval(int value) +void KisConfig::setStabilizerDelayedPaint(bool value) { - m_cfg.writeEntry("stabilizerDelayedPaintInterval", value); + m_cfg.writeEntry("stabilizerDelayedPaint", value); } QString KisConfig::customFFMpegPath(bool defaultValue) const diff --git a/libs/ui/tool/KisStabilizerDelayedPaintHelper.h b/libs/ui/tool/KisStabilizerDelayedPaintHelper.h --- a/libs/ui/tool/KisStabilizerDelayedPaintHelper.h +++ b/libs/ui/tool/KisStabilizerDelayedPaintHelper.h @@ -43,6 +43,7 @@ QTimer m_paintTimer; QQueue m_paintQueue; int m_lastPendingTime; + int m_lastPaintTime; QElapsedTimer m_elapsedTimer; // Callbacks @@ -74,13 +75,14 @@ m_requestUpdateOutline = requestUpdateOutline; } - void start(int paintInterval, const KisPaintInformation &firstPaintInfo); + void start(const KisPaintInformation &firstPaintInfo); void update(const QVector &newPaintInfos); + void paintSome(); void end(); void cancel(); private Q_SLOTS: - void stabilizerDelayedPaint(bool isEndStroke = false); + void stabilizerDelayedPaintTimer(); }; #endif // KIS_STABILIZER_DELAYED_PAINT_HELPER_H diff --git a/libs/ui/tool/KisStabilizerDelayedPaintHelper.cpp b/libs/ui/tool/KisStabilizerDelayedPaintHelper.cpp --- a/libs/ui/tool/KisStabilizerDelayedPaintHelper.cpp +++ b/libs/ui/tool/KisStabilizerDelayedPaintHelper.cpp @@ -18,25 +18,28 @@ #include "KisStabilizerDelayedPaintHelper.h" +constexpr int fixedPaintTimerInterval = 20; + KisStabilizerDelayedPaintHelper::TimedPaintInfo::TimedPaintInfo(int elapsedTime, KisPaintInformation paintInfo) : elapsedTime(elapsedTime) , paintInfo(paintInfo) { } KisStabilizerDelayedPaintHelper::KisStabilizerDelayedPaintHelper() { - connect(&m_paintTimer, SIGNAL(timeout()), SLOT(stabilizerDelayedPaint())); + connect(&m_paintTimer, SIGNAL(timeout()), SLOT(stabilizerDelayedPaintTimer())); } -void KisStabilizerDelayedPaintHelper::start(int paintInterval, const KisPaintInformation &firstPaintInfo) { +void KisStabilizerDelayedPaintHelper::start(const KisPaintInformation &firstPaintInfo) { if (running()) { cancel(); } - m_paintTimer.setInterval(paintInterval); + m_paintTimer.setInterval(fixedPaintTimerInterval); m_paintTimer.start(); m_elapsedTimer.start(); m_lastPendingTime = m_elapsedTimer.elapsed(); + m_lastPaintTime = m_lastPendingTime; m_paintQueue.enqueue(TimedPaintInfo(m_lastPendingTime, firstPaintInfo)); } @@ -51,35 +54,44 @@ m_lastPendingTime = now; } +void KisStabilizerDelayedPaintHelper::paintSome() { + // This function is also called from KisToolFreehandHelper::paint + m_lastPaintTime = m_elapsedTimer.elapsed(); + if (m_paintQueue.isEmpty()) { + return; + } + int now = m_lastPaintTime; + // Always keep one in the queue since painting requires two points + while (m_paintQueue.size() > 1 && m_paintQueue.head().elapsedTime <= now) { + const TimedPaintInfo dequeued = m_paintQueue.dequeue(); + m_paintLine(dequeued.paintInfo, m_paintQueue.head().paintInfo); + } +} + void KisStabilizerDelayedPaintHelper::end() { - stabilizerDelayedPaint(true); m_paintTimer.stop(); + m_elapsedTimer.invalidate(); + if (m_paintQueue.isEmpty()) { + return; + } + TimedPaintInfo dequeued = m_paintQueue.dequeue(); + while (!m_paintQueue.isEmpty()) { + const TimedPaintInfo dequeued2 = m_paintQueue.dequeue(); + m_paintLine(dequeued.paintInfo, dequeued2.paintInfo); + dequeued = dequeued2; + } } void KisStabilizerDelayedPaintHelper::cancel() { m_paintTimer.stop(); m_paintQueue.clear(); } -void KisStabilizerDelayedPaintHelper::stabilizerDelayedPaint(bool isEndStroke) { - if (m_paintQueue.isEmpty()) { - return; - } - if (isEndStroke) { - TimedPaintInfo dequeued = m_paintQueue.dequeue(); - while (!m_paintQueue.isEmpty()) { - const TimedPaintInfo dequeued2 = m_paintQueue.dequeue(); - m_paintLine(dequeued.paintInfo, dequeued2.paintInfo); - dequeued = dequeued2; - } - m_requestUpdateOutline(); +void KisStabilizerDelayedPaintHelper::stabilizerDelayedPaintTimer() { + if (m_elapsedTimer.elapsed() - m_lastPaintTime < fixedPaintTimerInterval) { return; } - int now = m_elapsedTimer.elapsed(); - // Always keep one in the queue since painting requires two points - while (m_paintQueue.size() > 1 && m_paintQueue.head().elapsedTime <= now) { - const TimedPaintInfo dequeued = m_paintQueue.dequeue(); - m_paintLine(dequeued.paintInfo, m_paintQueue.head().paintInfo); - } + paintSome(); + // Explicitly update the outline because this is outside the pointer event m_requestUpdateOutline(); } diff --git a/libs/ui/tool/kis_tool_freehand_helper.cpp b/libs/ui/tool/kis_tool_freehand_helper.cpp --- a/libs/ui/tool/kis_tool_freehand_helper.cpp +++ b/libs/ui/tool/kis_tool_freehand_helper.cpp @@ -586,6 +586,11 @@ if (m_d->smoothingOptions->smoothingType() == KisSmoothingOptions::STABILIZER) { m_d->stabilizedSampler.addEvent(info); + if (m_d->stabilizerDelayedPaintHelper.running()) { + // Paint here so we don't have to rely on the timer + // This is just a tricky source for a relatively stable 7ms "timer" + m_d->stabilizerDelayedPaintHelper.paintSome(); + } } else { m_d->previousPaintInformation = info; } @@ -681,9 +686,9 @@ m_d->stabilizerPollTimer.setInterval(stabilizerSampleSize); m_d->stabilizerPollTimer.start(); - int delayedPaintInterval = cfg.stabilizerDelayedPaintInterval(); - if (delayedPaintInterval < stabilizerSampleSize) { - m_d->stabilizerDelayedPaintHelper.start(delayedPaintInterval, firstPaintInfo); + bool delayedPaintEnabled = cfg.stabilizerDelayedPaint(); + if (delayedPaintEnabled) { + m_d->stabilizerDelayedPaintHelper.start(firstPaintInfo); } m_d->stabilizedSampler.clear(); @@ -975,4 +980,3 @@ { m_d->canvasMirroredH = mirrored; } -