[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-kimageshop
Subject: [krita] libs: FEATURE: auto-smoothing for bezier curve tools
From: Dmitry Kazakov <null () kde ! org>
Date: 2018-08-23 15:52:46
Message-ID: E1fsrug-0003bX-VB () code ! kde ! org
[Download RAW message or body]
Git commit 58444e98e7a230c50dcc27f6705d6e2da919e63d by Dmitry Kazakov.
Committed on 23/08/2018 at 15:52.
Pushed by dkazakov into branch 'master'.
FEATURE: auto-smoothing for bezier curve tools
Now if you select auto-smoothing the cerated curve will
be not a "polygon", but a smooth curve with the type of all the
points set to "smooth".
BUG:351787
CC:kimageshop@kde.org
M +48 -0 libs/basicflakes/tools/KoCreatePathTool.cpp
M +4 -0 libs/basicflakes/tools/KoCreatePathTool.h
M +17 -0 libs/basicflakes/tools/KoCreatePathTool_p.h
M +25 -16 libs/flake/commands/KoPathPointTypeCommand.cpp
M +2 -0 libs/flake/commands/KoPathPointTypeCommand.h
M +10 -0 libs/ui/kis_config.cc
M +3 -0 libs/ui/kis_config.h
https://commits.kde.org/krita/58444e98e7a230c50dcc27f6705d6e2da919e63d
diff --git a/libs/basicflakes/tools/KoCreatePathTool.cpp \
b/libs/basicflakes/tools/KoCreatePathTool.cpp index c2063193bb2..fa54cfdd5e0 100644
--- a/libs/basicflakes/tools/KoCreatePathTool.cpp
+++ b/libs/basicflakes/tools/KoCreatePathTool.cpp
@@ -34,6 +34,7 @@
#include <KoColor.h>
#include "kis_canvas_resource_provider.h"
#include <KisHandlePainterHelper.h>
+#include "KoPathPointTypeCommand.h"
#include <klocalizedstring.h>
@@ -290,6 +291,38 @@ void KoCreatePathTool::mouseMoveEvent(KoPointerEvent *event)
}
} else {
d->activePoint->setPoint(snappedPosition);
+
+ if (!d->prevPointWasDragged && d->autoSmoothCurves) {
+ KoPathPointIndex index = d->shape->pathPointIndex(d->activePoint);
+ if (index.second > 0) {
+
+ KoPathPointIndex prevIndex(index.first, index.second - 1);
+ KoPathPoint *prevPoint = d->shape->pointByIndex(prevIndex);
+
+ if (prevPoint) {
+ KoPathPoint *prevPrevPoint = 0;
+
+ if (index.second > 1) {
+ KoPathPointIndex prevPrevIndex(index.first, index.second - \
2); + prevPrevPoint = d->shape->pointByIndex(prevPrevIndex);
+ }
+
+ if (prevPrevPoint) {
+ const QPointF control1 = prevPoint->point() + 0.3 * \
(prevPrevPoint->point() - prevPoint->point()); + \
prevPoint->setControlPoint1(control1); + }
+
+ const QPointF control2 = prevPoint->point() + 0.3 * \
(d->activePoint->point() - prevPoint->point()); + \
prevPoint->setControlPoint2(control2); +
+ const QPointF activeControl = d->activePoint->point() + 0.3 * \
(prevPoint->point() - d->activePoint->point()); + \
d->activePoint->setControlPoint1(activeControl); +
+ KoPathPointTypeCommand::makeCubicPointSmooth(prevPoint);
+ }
+ }
+ }
+
}
canvas()->updateCanvas(d->shape->boundingRect());
@@ -304,6 +337,7 @@ void KoCreatePathTool::mouseReleaseEvent(KoPointerEvent *event)
d->listeningToModifiers = true; // After the first press-and-release
d->repaintActivePoint();
+ d->prevPointWasDragged = d->pointIsDragged;
d->pointIsDragged = false;
KoPathPoint *lastActivePoint = d->activePoint;
@@ -325,6 +359,11 @@ void KoCreatePathTool::mouseReleaseEvent(KoPointerEvent *event)
d->firstPoint->setControlPoint1(d->activePoint->controlPoint1());
delete d->shape->removePoint(d->shape->pathPointIndex(d->activePoint));
d->activePoint = d->firstPoint;
+
+ if (!d->prevPointWasDragged && d->autoSmoothCurves) {
+ KoPathPointTypeCommand::makeCubicPointSmooth(d->activePoint);
+ }
+
d->shape->closeMerge();
// we are closing the path, so reset the existing start path point
@@ -408,6 +447,7 @@ void KoCreatePathTool::activate(ToolActivation activation, const \
QSet<KoShape*>
// retrieve the actual global handle radius
d->handleRadius = handleRadius();
+ d->loadAutoSmoothValueFromConfig();
// reset snap guide
canvas()->updateCanvas(canvas()->snapGuide()->boundingRect());
@@ -502,6 +542,14 @@ QList<QPointer<QWidget> > \
KoCreatePathTool::createOptionWidgets()
QList<QPointer<QWidget> > list;
+ QCheckBox *smoothCurves = new QCheckBox(i18n("Autosmooth curve"));
+ smoothCurves->setObjectName("smooth-curves-widget");
+ smoothCurves->setChecked(d->autoSmoothCurves);
+ connect(smoothCurves, SIGNAL(toggled(bool)), this, \
SLOT(autoSmoothCurvesChanged(bool))); + connect(this, \
SIGNAL(sigUpdateAutoSmoothCurvesGUI(bool)), smoothCurves, SLOT(setChecked(bool))); +
+ list.append(smoothCurves);
+
QWidget *angleWidget = new QWidget();
angleWidget->setObjectName("Angle Constraints");
QGridLayout *layout = new QGridLayout(angleWidget);
diff --git a/libs/basicflakes/tools/KoCreatePathTool.h \
b/libs/basicflakes/tools/KoCreatePathTool.h index 3924e354f1b..a1c5a437e96 100644
--- a/libs/basicflakes/tools/KoCreatePathTool.h
+++ b/libs/basicflakes/tools/KoCreatePathTool.h
@@ -81,6 +81,9 @@ public Q_SLOTS:
/// reimplemented
void documentResourceChanged(int key, const QVariant & res) override;
+Q_SIGNALS:
+ void sigUpdateAutoSmoothCurvesGUI(bool value);
+
protected:
/**
* Add path shape to document.
@@ -109,5 +112,6 @@ private:
Q_DECLARE_PRIVATE(KoCreatePathTool)
Q_PRIVATE_SLOT(d_func(), void angleDeltaChanged(int))
Q_PRIVATE_SLOT(d_func(), void angleSnapChanged(int))
+ Q_PRIVATE_SLOT(d_func(), void autoSmoothCurvesChanged(bool))
};
#endif
diff --git a/libs/basicflakes/tools/KoCreatePathTool_p.h \
b/libs/basicflakes/tools/KoCreatePathTool_p.h index 2f68d9f4794..c6b863a56c1 100644
--- a/libs/basicflakes/tools/KoCreatePathTool_p.h
+++ b/libs/basicflakes/tools/KoCreatePathTool_p.h
@@ -31,6 +31,7 @@
#include "KoSnapStrategy.h"
#include "KoToolBase_p.h"
#include <KoViewConverter.h>
+#include "kis_config.h"
#include "math.h"
@@ -205,6 +206,8 @@ public:
PathConnectionPoint existingEndPoint; ///< an existing path point we finished \
a new path at
KoPathPoint *hoveredPoint; ///< an existing path end point the mouse is hovering \
on
bool listeningToModifiers; // Fine tune when to begin processing modifiers at \
the beginning of a stroke. + bool prevPointWasDragged = false;
+ bool autoSmoothCurves = false;
QPointF dragStartPoint;
@@ -415,6 +418,20 @@ public:
angleSnapStrategy->setAngleStep(angleSnappingDelta);
}
+ void autoSmoothCurvesChanged(bool value) {
+ autoSmoothCurves = value;
+
+ KisConfig cfg(false);
+ cfg.setAutoSmoothBezierCurves(value);
+ }
+
+ void loadAutoSmoothValueFromConfig() {
+ KisConfig cfg(true);
+ autoSmoothCurves = cfg.autoSmoothBezierCurves();
+
+ emit q->sigUpdateAutoSmoothCurvesGUI(autoSmoothCurves);
+ }
+
void angleSnapChanged(int angleSnap) {
angleSnapStatus = ! angleSnapStatus;
if (angleSnapStrategy) {
diff --git a/libs/flake/commands/KoPathPointTypeCommand.cpp \
b/libs/flake/commands/KoPathPointTypeCommand.cpp index d61ac53e7b5..b87215a7e68 \
100644
--- a/libs/flake/commands/KoPathPointTypeCommand.cpp
+++ b/libs/flake/commands/KoPathPointTypeCommand.cpp
@@ -106,6 +106,7 @@ void KoPathPointTypeCommand::redo()
} else
point->setControlPoint2(cubic.first()->controlPoint2());
}
+ point->setProperties(properties);
break;
}
case Symmetric: {
@@ -126,33 +127,20 @@ void KoPathPointTypeCommand::redo()
// the new distance of the control points is the average distance to the \
node point
point->setControlPoint1(point->point() + 0.5 * averageLength * \
(directionC1 - directionC2));
point->setControlPoint2(point->point() + 0.5 * averageLength * \
(directionC2 - directionC1)); + point->setProperties(properties);
}
break;
case Smooth: {
- properties &= ~KoPathPoint::IsSymmetric;
- properties |= KoPathPoint::IsSmooth;
-
- // calculate vector from node point to first control point and normalize \
it
- QPointF directionC1 = point->controlPoint1() - point->point();
- qreal dirLengthC1 = sqrt(directionC1.x() * directionC1.x() + \
directionC1.y() * directionC1.y());
- directionC1 /= dirLengthC1;
- // calculate vector from node point to second control point and \
normalize it
- QPointF directionC2 = point->controlPoint2() - point->point();
- qreal dirLengthC2 = sqrt(directionC2.x() * directionC2.x() + \
directionC2.y() * directionC2.y());
- directionC2 /= dirLengthC2;
- // compute position of the control points so that they lie on a line \
going through the node point
- // the new distance of the control points is the average distance to the \
node point
- point->setControlPoint1(point->point() + 0.5 * dirLengthC1 * \
(directionC1 - directionC2));
- point->setControlPoint2(point->point() + 0.5 * dirLengthC2 * \
(directionC2 - directionC1)); + makeCubicPointSmooth(point);
}
break;
case Corner:
default:
properties &= ~KoPathPoint::IsSymmetric;
properties &= ~KoPathPoint::IsSmooth;
+ point->setProperties(properties);
break;
}
- point->setProperties(properties);
}
repaint(true);
}
@@ -186,6 +174,27 @@ void KoPathPointTypeCommand::undo()
repaint(true);
}
+void KoPathPointTypeCommand::makeCubicPointSmooth(KoPathPoint *point)
+{
+ KoPathPoint::PointProperties properties = point->properties();
+
+ properties &= ~KoPathPoint::IsSymmetric;
+ properties |= KoPathPoint::IsSmooth;
+
+ // calculate vector from node point to first control point and normalize it
+ QPointF directionC1 = point->controlPoint1() - point->point();
+ qreal dirLengthC1 = sqrt(directionC1.x() * directionC1.x() + directionC1.y() * \
directionC1.y()); + directionC1 /= dirLengthC1;
+ // calculate vector from node point to second control point and normalize it
+ QPointF directionC2 = point->controlPoint2() - point->point();
+ qreal dirLengthC2 = sqrt(directionC2.x() * directionC2.x() + directionC2.y() * \
directionC2.y()); + directionC2 /= dirLengthC2;
+ // compute position of the control points so that they lie on a line going \
through the node point + // the new distance of the control points is the average \
distance to the node point + point->setControlPoint1(point->point() + 0.5 * \
dirLengthC1 * (directionC1 - directionC2)); + \
point->setControlPoint2(point->point() + 0.5 * dirLengthC2 * (directionC2 - \
directionC1)); +}
+
void KoPathPointTypeCommand::undoChanges(const QList<PointData> &data)
{
QList<PointData>::const_iterator it(data.begin());
diff --git a/libs/flake/commands/KoPathPointTypeCommand.h \
b/libs/flake/commands/KoPathPointTypeCommand.h index 849ec8b8040..f025a2314f8 100644
--- a/libs/flake/commands/KoPathPointTypeCommand.h
+++ b/libs/flake/commands/KoPathPointTypeCommand.h
@@ -54,6 +54,8 @@ public:
/// revert the actions done in redo
void undo() override;
+ static void makeCubicPointSmooth(KoPathPoint *point);
+
private:
// used for storing the data for undo
struct PointData {
diff --git a/libs/ui/kis_config.cc b/libs/ui/kis_config.cc
index 9b224e836e7..f0cafa11754 100644
--- a/libs/ui/kis_config.cc
+++ b/libs/ui/kis_config.cc
@@ -1965,6 +1965,16 @@ void KisConfig::setDefaultAssistantsColor(const QColor &color) \
const m_cfg.writeEntry("defaultAssistantsColor", color);
}
+bool KisConfig::autoSmoothBezierCurves(bool defaultValue) const
+{
+ return defaultValue ? false : m_cfg.readEntry("autoSmoothBezierCurves", false);
+}
+
+void KisConfig::setAutoSmoothBezierCurves(bool value)
+{
+ m_cfg.writeEntry("autoSmoothBezierCurves", value);
+}
+
#include <QDomDocument>
#include <QDomElement>
diff --git a/libs/ui/kis_config.h b/libs/ui/kis_config.h
index a8f04c75e26..c0d24bef74f 100644
--- a/libs/ui/kis_config.h
+++ b/libs/ui/kis_config.h
@@ -566,6 +566,9 @@ public:
QColor defaultAssistantsColor(bool defaultValue = false) const;
void setDefaultAssistantsColor(const QColor &color) const;
+ bool autoSmoothBezierCurves(bool defaultValue = false) const;
+ void setAutoSmoothBezierCurves(bool value);
+
template<class T>
void writeEntry(const QString& name, const T& value) {
m_cfg.writeEntry(name, value);
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic