[krita] /: FEATURE: round corners for rectangular tools

Dmitry Kazakov null at kde.org
Thu Aug 23 16:52:47 BST 2018


Git commit 04931e4fc85ef967a2d3834993890a430a65a864 by Dmitry Kazakov.
Committed on 23/08/2018 at 15:52.
Pushed by dkazakov into branch 'master'.

FEATURE: round corners for rectangular tools

Now both rectangular tools have an ability to set round
corners for the resulting shape. It works both: for vector
and raster shapes

BUG:335568
CC:kimageshop at kde.org

M  +101  -33   libs/ui/forms/wdgrectangleconstraints.ui
M  +54   -2    libs/ui/tool/kis_rectangle_constraint_widget.cpp
M  +8    -1    libs/ui/tool/kis_rectangle_constraint_widget.h
M  +22   -13   libs/ui/tool/kis_shape_tool_helper.cpp
M  +1    -1    libs/ui/tool/kis_shape_tool_helper.h
M  +6    -0    libs/ui/tool/kis_tool.cc
M  +1    -0    libs/ui/tool/kis_tool.h
M  +5    -0    libs/ui/tool/kis_tool_ellipse_base.cpp
M  +3    -0    libs/ui/tool/kis_tool_ellipse_base.h
M  +38   -4    libs/ui/tool/kis_tool_rectangle_base.cpp
M  +7    -2    libs/ui/tool/kis_tool_rectangle_base.h
M  +8    -10   plugins/flake/pathshapes/rectangle/RectangleShape.cpp
M  +24   -0    plugins/flake/pathshapes/rectangle/RectangleShapeFactory.cpp
M  +2    -0    plugins/flake/pathshapes/rectangle/RectangleShapeFactory.h
M  +4    -1    plugins/tools/basictools/kis_tool_ellipse.cc
M  +1    -1    plugins/tools/basictools/kis_tool_ellipse.h
M  +15   -4    plugins/tools/basictools/kis_tool_rectangle.cc
M  +1    -1    plugins/tools/basictools/kis_tool_rectangle.h
M  +4    -1    plugins/tools/selectiontools/kis_tool_select_elliptical.cc
M  +1    -1    plugins/tools/selectiontools/kis_tool_select_elliptical.h
M  +12   -3    plugins/tools/selectiontools/kis_tool_select_rectangular.cc
M  +1    -1    plugins/tools/selectiontools/kis_tool_select_rectangular.h

https://commits.kde.org/krita/04931e4fc85ef967a2d3834993890a430a65a864

diff --git a/libs/ui/forms/wdgrectangleconstraints.ui b/libs/ui/forms/wdgrectangleconstraints.ui
index c232202b2f8..ccb9d1b86db 100644
--- a/libs/ui/forms/wdgrectangleconstraints.ui
+++ b/libs/ui/forms/wdgrectangleconstraints.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>230</width>
-    <height>149</height>
+    <width>243</width>
+    <height>328</height>
    </rect>
   </property>
   <property name="sizePolicy">
@@ -19,23 +19,8 @@
   <property name="windowTitle">
    <string>Size</string>
   </property>
-  <layout class="QGridLayout" name="gridLayout_2">
-   <property name="leftMargin">
-    <number>0</number>
-   </property>
-   <property name="topMargin">
-    <number>0</number>
-   </property>
-   <property name="rightMargin">
-    <number>0</number>
-   </property>
-   <property name="bottomMargin">
-    <number>0</number>
-   </property>
-   <property name="spacing">
-    <number>0</number>
-   </property>
-   <item row="0" column="0">
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
     <layout class="QGridLayout" name="gridLayout">
      <property name="leftMargin">
       <number>7</number>
@@ -84,6 +69,12 @@
      </item>
      <item row="1" column="2">
       <widget class="KisIntParseSpinBox" name="intHeight">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
        <property name="toolTip">
         <string>Height</string>
        </property>
@@ -107,6 +98,12 @@
      </item>
      <item row="2" column="2">
       <widget class="KisDoubleParseSpinBox" name="doubleRatio">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
        <property name="toolTip">
         <string>Aspect ratio</string>
        </property>
@@ -120,6 +117,12 @@
      </item>
      <item row="0" column="2">
       <widget class="KisIntParseSpinBox" name="intWidth">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
        <property name="toolTip">
         <string>Width</string>
        </property>
@@ -153,20 +156,79 @@
      </item>
     </layout>
    </item>
-   <item row="0" column="1">
-    <spacer name="horizontalSpacer">
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
-     <property name="sizeHint" stdset="0">
-      <size>
-       <width>40</width>
-       <height>20</height>
-      </size>
-     </property>
-    </spacer>
+   <item>
+    <layout class="QGridLayout" name="gridLayout_2">
+     <item row="0" column="0">
+      <widget class="QLabel" name="lblRoundCornersX">
+       <property name="text">
+        <string>Round X:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="KisIntParseSpinBox" name="intRoundCornersX">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="toolTip">
+        <string>Height</string>
+       </property>
+       <property name="suffix">
+        <string> px</string>
+       </property>
+       <property name="maximum">
+        <number>99999</number>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="2" rowspan="2">
+      <widget class="KoAspectButton" name="cornersAspectButton" native="true">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>24</width>
+         <height>24</height>
+        </size>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="0">
+      <widget class="QLabel" name="lblRoundCornersY">
+       <property name="text">
+        <string>Round Y:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="1">
+      <widget class="KisIntParseSpinBox" name="intRoundCornersY">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="toolTip">
+        <string>Height</string>
+       </property>
+       <property name="suffix">
+        <string> px</string>
+       </property>
+       <property name="maximum">
+        <number>99999</number>
+       </property>
+      </widget>
+     </item>
+    </layout>
    </item>
-   <item row="1" column="0">
+   <item>
     <spacer name="verticalSpacer">
      <property name="orientation">
       <enum>Qt::Vertical</enum>
@@ -174,7 +236,7 @@
      <property name="sizeHint" stdset="0">
       <size>
        <width>20</width>
-       <height>40</height>
+       <height>187</height>
       </size>
      </property>
     </spacer>
@@ -192,6 +254,12 @@
    <extends>QDoubleSpinBox</extends>
    <header>kis_double_parse_spin_box.h</header>
   </customwidget>
+  <customwidget>
+   <class>KoAspectButton</class>
+   <extends>QWidget</extends>
+   <header>KoAspectButton.h</header>
+   <container>1</container>
+  </customwidget>
  </customwidgets>
  <resources/>
  <connections/>
diff --git a/libs/ui/tool/kis_rectangle_constraint_widget.cpp b/libs/ui/tool/kis_rectangle_constraint_widget.cpp
index 0b0f1247922..83b03c47942 100644
--- a/libs/ui/tool/kis_rectangle_constraint_widget.cpp
+++ b/libs/ui/tool/kis_rectangle_constraint_widget.cpp
@@ -18,8 +18,13 @@
 #include "kis_tool_rectangle_base.h"
 
 #include <kis_icon.h>
+#include "kis_aspect_ratio_locker.h"
+#include "kis_signals_blocker.h"
+#include <KConfigGroup>
+#include <KSharedConfig>
 
-KisRectangleConstraintWidget::KisRectangleConstraintWidget(QWidget *parent, KisToolRectangleBase *tool) : QWidget(parent) 
+KisRectangleConstraintWidget::KisRectangleConstraintWidget(QWidget *parent, KisToolRectangleBase *tool, bool showRoundCornersGUI)
+    : QWidget(parent)
 {
     m_tool = tool;
     
@@ -38,6 +43,23 @@ KisRectangleConstraintWidget::KisRectangleConstraintWidget(QWidget *parent, KisT
   
     connect(this, SIGNAL(constraintsChanged(bool,bool,bool,float,float,float)), m_tool, SLOT(constraintsChanged(bool,bool,bool,float,float,float)));
     connect(m_tool, SIGNAL(rectangleChanged(QRectF)), this, SLOT(rectangleChanged(QRectF)));
+
+    m_cornersAspectLocker = new KisAspectRatioLocker(this);
+    m_cornersAspectLocker->connectSpinBoxes(intRoundCornersX, intRoundCornersY, cornersAspectButton);
+
+    connect(m_cornersAspectLocker, SIGNAL(sliderValueChanged()), SLOT(slotRoundCornersChanged()));
+    connect(m_cornersAspectLocker, SIGNAL(aspectButtonChanged()), SLOT(slotRoundCornersAspectLockChanged()));
+
+    connect(m_tool, SIGNAL(sigRequestReloadConfig()), SLOT(slotReloadConfig()));
+    slotReloadConfig();
+
+    if (!showRoundCornersGUI) {
+        intRoundCornersX->setVisible(false);
+        intRoundCornersY->setVisible(false);
+        lblRoundCornersX->setVisible(false);
+        lblRoundCornersY->setVisible(false);
+        cornersAspectButton->setVisible(false);
+    }
 }
 
 void KisRectangleConstraintWidget::inputsChanged() 
@@ -49,7 +71,37 @@ void KisRectangleConstraintWidget::inputsChanged()
         doubleRatio->value(), 
         intWidth->value(), 
         intHeight->value()
-    );
+                );
+}
+
+void KisRectangleConstraintWidget::slotRoundCornersChanged()
+{
+    m_tool->roundCornersChanged(intRoundCornersX->value(), intRoundCornersY->value());
+
+    KConfigGroup cfg = KSharedConfig::openConfig()->group(m_tool->toolId());
+    cfg.writeEntry("roundCornersX", intRoundCornersX->value());
+    cfg.writeEntry("roundCornersY", intRoundCornersY->value());
+}
+
+void KisRectangleConstraintWidget::slotRoundCornersAspectLockChanged()
+{
+    KConfigGroup cfg = KSharedConfig::openConfig()->group(m_tool->toolId());
+    cfg.writeEntry("roundCornersAspectLocked", cornersAspectButton->keepAspectRatio());
+}
+
+void KisRectangleConstraintWidget::slotReloadConfig()
+{
+    KConfigGroup cfg = KSharedConfig::openConfig()->group(m_tool->toolId());
+
+    {
+        KisSignalsBlocker b(intRoundCornersX, intRoundCornersY, cornersAspectButton);
+        intRoundCornersX->setValue(cfg.readEntry("roundCornersX", 0));
+        intRoundCornersY->setValue(cfg.readEntry("roundCornersY", 0));
+        cornersAspectButton->setKeepAspectRatio(cfg.readEntry("roundCornersAspectLocked", true));
+        m_cornersAspectLocker->updateAspect();
+    }
+
+    slotRoundCornersChanged();
 }
 
 void KisRectangleConstraintWidget::rectangleChanged(const QRectF &rect) 
diff --git a/libs/ui/tool/kis_rectangle_constraint_widget.h b/libs/ui/tool/kis_rectangle_constraint_widget.h
index fc803db6e4c..f4cfdefb4df 100644
--- a/libs/ui/tool/kis_rectangle_constraint_widget.h
+++ b/libs/ui/tool/kis_rectangle_constraint_widget.h
@@ -21,13 +21,14 @@
 #include <kritaui_export.h>
 
 class KisToolRectangleBase;
+class KisAspectRatioLocker;
 
 class KRITAUI_EXPORT KisRectangleConstraintWidget : public QWidget, public Ui::WdgRectangleConstraints
 {
   Q_OBJECT
   
 public:
-    KisRectangleConstraintWidget(QWidget *parentWidget, KisToolRectangleBase *tool);
+    KisRectangleConstraintWidget(QWidget *parentWidget, KisToolRectangleBase *tool, bool showRoundCornersGUI);
     
 Q_SIGNALS:
   void constraintsChanged(bool forceRatio, bool forceWidth, bool forceHeight, float ratio, float width, float height);
@@ -35,10 +36,16 @@ Q_SIGNALS:
 protected Q_SLOTS:
   void rectangleChanged(const QRectF &rect);
   void inputsChanged();
+
+  void slotRoundCornersChanged();
+  void slotRoundCornersAspectLockChanged();
+
+  void slotReloadConfig();
   
 protected:
   KisToolRectangleBase* m_tool;
   Ui_WdgRectangleConstraints *m_widget;
+  KisAspectRatioLocker *m_cornersAspectLocker;
 };
 
 #endif
diff --git a/libs/ui/tool/kis_shape_tool_helper.cpp b/libs/ui/tool/kis_shape_tool_helper.cpp
index 54552765d0b..4edab2a3d73 100644
--- a/libs/ui/tool/kis_shape_tool_helper.cpp
+++ b/libs/ui/tool/kis_shape_tool_helper.cpp
@@ -21,26 +21,35 @@
 #include <KoPathShape.h>
 #include <KoShapeRegistry.h>
 #include <KoShapeFactoryBase.h>
+#include <KoProperties.h>
 
-KoShape* KisShapeToolHelper::createRectangleShape(const QRectF& rect)
+
+KoShape* KisShapeToolHelper::createRectangleShape(const QRectF& rect, qreal roundCornersX, qreal roundCornersY)
 {
     KoShape* shape;
+
     KoShapeFactoryBase *rectFactory = KoShapeRegistry::instance()->value("RectangleShape");
     if (rectFactory) {
-        shape = rectFactory->createDefaultShape();
-        shape->setSize(rect.size());
-        shape->setPosition(rect.topLeft());
+        KoProperties props;
+        props.setProperty("x", rect.x());
+        props.setProperty("y", rect.y());
+        props.setProperty("width", rect.width());
+        props.setProperty("height", rect.height());
+        props.setProperty("rx", 2 * 100.0 * roundCornersX / rect.width());
+        props.setProperty("ry", 2 * 100.0 * roundCornersY / rect.height());
+
+        shape = rectFactory->createShape(&props);
     } else {
         //Fallback if the plugin wasn't found
-        KoPathShape* path = new KoPathShape();
-        path->setShapeId(KoPathShapeId);
-        path->moveTo(rect.topLeft());
-        path->lineTo(rect.topLeft() + QPointF(rect.width(), 0));
-        path->lineTo(rect.bottomRight());
-        path->lineTo(rect.topLeft() + QPointF(0, rect.height()));
-        path->close();
-        path->normalize();
-        shape = path;
+        QPainterPath path;
+        if (roundCornersX > 0 || roundCornersY > 0) {
+            path.addRoundedRect(rect, roundCornersX, roundCornersY);
+        } else {
+            path.addRect(rect);
+        }
+        KoPathShape *pathShape = KoPathShape::createShapeFromPainterPath(path);
+        pathShape->normalize();
+        shape = pathShape;
     }
     return shape;
 }
diff --git a/libs/ui/tool/kis_shape_tool_helper.h b/libs/ui/tool/kis_shape_tool_helper.h
index 60e3074907c..36d18b10c8b 100644
--- a/libs/ui/tool/kis_shape_tool_helper.h
+++ b/libs/ui/tool/kis_shape_tool_helper.h
@@ -30,7 +30,7 @@ class KoShape;
 class KRITAUI_EXPORT KisShapeToolHelper
 {
 public:
-    static KoShape* createRectangleShape(const QRectF& rect);
+    static KoShape* createRectangleShape(const QRectF& rect, qreal roundCornersX, qreal roundCornersY);
 
     static KoShape* createEllipseShape(const QRectF& rect);
 
diff --git a/libs/ui/tool/kis_tool.cc b/libs/ui/tool/kis_tool.cc
index f9ee6ee555e..c6091e2e374 100644
--- a/libs/ui/tool/kis_tool.cc
+++ b/libs/ui/tool/kis_tool.cc
@@ -297,6 +297,12 @@ QRectF KisTool::convertToPt(const QRectF &rect)
     return r;
 }
 
+qreal KisTool::convertToPt(qreal value)
+{
+    const qreal avgResolution = 0.5 * (image()->xRes() + image()->yRes());
+    return value / avgResolution;
+}
+
 QPointF KisTool::pixelToView(const QPoint &pixelCoord) const
 {
     if (!image())
diff --git a/libs/ui/tool/kis_tool.h b/libs/ui/tool/kis_tool.h
index dcf5368519d..efede6c1fd7 100644
--- a/libs/ui/tool/kis_tool.h
+++ b/libs/ui/tool/kis_tool.h
@@ -216,6 +216,7 @@ protected:
     QPoint convertToImagePixelCoordFloored(KoPointerEvent *e);
 
     QRectF convertToPt(const QRectF &rect);
+    qreal convertToPt(qreal value);
 
     QPointF viewToPixel(const QPointF &viewCoord) const;
     /// Convert an integer pixel coordinate into a view coordinate.
diff --git a/libs/ui/tool/kis_tool_ellipse_base.cpp b/libs/ui/tool/kis_tool_ellipse_base.cpp
index fa291d2d936..5ea46fb4674 100644
--- a/libs/ui/tool/kis_tool_ellipse_base.cpp
+++ b/libs/ui/tool/kis_tool_ellipse_base.cpp
@@ -41,3 +41,8 @@ void KisToolEllipseBase::paintRectangle(QPainter &gc, const QRectF &imageRect)
     path.addEllipse(viewRect);
     paintToolOutline(&gc, path);
 }
+
+bool KisToolEllipseBase::showRoundCornersGUI() const
+{
+    return false;
+}
diff --git a/libs/ui/tool/kis_tool_ellipse_base.h b/libs/ui/tool/kis_tool_ellipse_base.h
index 8d5231f9e55..487c80a3f56 100644
--- a/libs/ui/tool/kis_tool_ellipse_base.h
+++ b/libs/ui/tool/kis_tool_ellipse_base.h
@@ -29,6 +29,9 @@ public:
     KisToolEllipseBase(KoCanvasBase * canvas, KisToolEllipseBase::ToolType type, const QCursor & cursor=KisCursor::load("tool_ellipse_cursor.png", 6, 6));
 
     void paintRectangle(QPainter &gc, const QRectF &imageRect) override;
+
+protected:
+    bool showRoundCornersGUI() const override;
 };
 
 #endif // KIS_TOOL_ELLIPSE_BASE_H
diff --git a/libs/ui/tool/kis_tool_rectangle_base.cpp b/libs/ui/tool/kis_tool_rectangle_base.cpp
index 1ae46e4b0e3..2c6e9270c23 100644
--- a/libs/ui/tool/kis_tool_rectangle_base.cpp
+++ b/libs/ui/tool/kis_tool_rectangle_base.cpp
@@ -25,6 +25,7 @@
 #include <KoCanvasBase.h>
 #include <KoCanvasController.h>
 #include <KoViewConverter.h>
+#include "kis_canvas2.h"
 
 #include "kis_rectangle_constraint_widget.h"
 
@@ -40,6 +41,8 @@ KisToolRectangleBase::KisToolRectangleBase(KoCanvasBase * canvas, KisToolRectang
     , m_forcedRatio(1.0)
     , m_forcedWidth(0)
     , m_forcedHeight(0)
+    , m_roundCornersX(0)
+    , m_roundCornersY(0)
 {
 }
 
@@ -48,7 +51,7 @@ QList<QPointer<QWidget> > KisToolRectangleBase::createOptionWidgets()
 {
   QList<QPointer<QWidget> > widgetsList = KisToolShape::createOptionWidgets();
 
-  widgetsList.append(new KisRectangleConstraintWidget(0, this));
+  widgetsList.append(new KisRectangleConstraintWidget(0, this, showRoundCornersGUI()));
 
   return widgetsList;
 }
@@ -67,6 +70,12 @@ void KisToolRectangleBase::constraintsChanged(bool forceRatio, bool forceWidth,
   if (ratio < 0.0001f) m_isRatioForced = false;
 }
 
+void KisToolRectangleBase::roundCornersChanged(int rx, int ry)
+{
+    m_roundCornersX = rx;
+    m_roundCornersY = ry;
+}
+
 void KisToolRectangleBase::paint(QPainter& gc, const KoViewConverter &converter)
 {
     if(mode() == KisTool::PAINT_MODE) {
@@ -76,6 +85,13 @@ void KisToolRectangleBase::paint(QPainter& gc, const KoViewConverter &converter)
     KisToolPaint::paint(gc, converter);
 }
 
+void KisToolRectangleBase::activate(KoToolBase::ToolActivation toolActivation, const QSet<KoShape *> &shapes)
+{
+    KisToolShape::activate(toolActivation, shapes);
+
+    emit sigRequestReloadConfig();
+}
+
 void KisToolRectangleBase::deactivate()
 {
     updateArea();
@@ -197,7 +213,7 @@ void KisToolRectangleBase::endPrimaryAction(KoPointerEvent *event)
 
     updateArea();
 
-    finishRect(createRect(m_dragStart, m_dragEnd));
+    finishRect(createRect(m_dragStart, m_dragEnd), m_roundCornersX, m_roundCornersY);
     event->accept();
 }
 
@@ -226,14 +242,32 @@ QRectF KisToolRectangleBase::createRect(const QPointF &start, const QPointF &end
     return result.normalized();
 }
 
+bool KisToolRectangleBase::showRoundCornersGUI() const
+{
+    return true;
+}
+
 void KisToolRectangleBase::paintRectangle(QPainter &gc, const QRectF &imageRect)
 {
     KIS_ASSERT_RECOVER_RETURN(canvas());
 
-    QRect viewRect = pixelToView(imageRect).toAlignedRect();
+    const QRect viewRect = pixelToView(imageRect).toAlignedRect();
+
+    KisCanvas2 *kritaCanvas = dynamic_cast<KisCanvas2*>(canvas());
+    KIS_SAFE_ASSERT_RECOVER_RETURN(kritaCanvas);
+
+    const KisCoordinatesConverter *converter = kritaCanvas->coordinatesConverter();
+    const qreal roundCornersX = converter->effectiveZoom() * m_roundCornersX;
+    const qreal roundCornersY = converter->effectiveZoom() * m_roundCornersY;
 
     QPainterPath path;
-    path.addRect(viewRect);
+
+    if (m_roundCornersX > 0 || m_roundCornersY > 0) {
+        path.addRoundedRect(viewRect,
+                            roundCornersX, roundCornersY);
+    } else {
+        path.addRect(viewRect);
+    }
     paintToolOutline(&gc, path);
 }
 
diff --git a/libs/ui/tool/kis_tool_rectangle_base.h b/libs/ui/tool/kis_tool_rectangle_base.h
index 3ab9b2116d4..f5684f092dc 100644
--- a/libs/ui/tool/kis_tool_rectangle_base.h
+++ b/libs/ui/tool/kis_tool_rectangle_base.h
@@ -29,10 +29,11 @@ Q_OBJECT
 
 Q_SIGNALS:
     void rectangleChanged(const QRectF &newRect);
+    void sigRequestReloadConfig();
 
 public Q_SLOTS:
     void constraintsChanged(bool forceRatio, bool forceWidth, bool forceHeight, float ratio, float width, float height);
-
+    void roundCornersChanged(int rx, int ry);
 public:
     enum ToolType {
         PAINT,
@@ -46,6 +47,7 @@ public:
     void endPrimaryAction(KoPointerEvent *event) override;
 
     void paint(QPainter& gc, const KoViewConverter &converter) override;
+    void activate(ToolActivation toolActivation, const QSet<KoShape*> &shapes) override;
     void deactivate() override;
     void listenToModifiers(bool listen) override;
     bool listeningToModifiers() override;
@@ -53,7 +55,7 @@ public:
     QList<QPointer<QWidget> > createOptionWidgets() override;
 
 protected:
-    virtual void finishRect(const QRectF&)=0;
+    virtual void finishRect(const QRectF &rect, qreal roundCornersX, qreal roundCornersY) = 0;
 
     QPointF m_dragCenter;
     QPointF m_dragStart;
@@ -67,6 +69,8 @@ protected:
     float m_forcedRatio;
     float m_forcedWidth;
     float m_forcedHeight;
+    int m_roundCornersX;
+    int m_roundCornersY;
 
     bool isFixedSize();
     void applyConstraints(QSizeF& area, bool overrideRatio);
@@ -74,6 +78,7 @@ protected:
     void updateArea();
     virtual void paintRectangle(QPainter &gc, const QRectF &imageRect);
     virtual QRectF createRect(const QPointF &start, const QPointF &end);
+    virtual bool showRoundCornersGUI() const;
 };
 
 #endif // KIS_TOOL_RECTANGLE_BASE_H
diff --git a/plugins/flake/pathshapes/rectangle/RectangleShape.cpp b/plugins/flake/pathshapes/rectangle/RectangleShape.cpp
index 3209bb7de79..6e0de7e4d37 100644
--- a/plugins/flake/pathshapes/rectangle/RectangleShape.cpp
+++ b/plugins/flake/pathshapes/rectangle/RectangleShape.cpp
@@ -300,11 +300,10 @@ qreal RectangleShape::cornerRadiusX() const
 
 void RectangleShape::setCornerRadiusX(qreal radius)
 {
-    if (radius >= 0.0 && radius <= 100.0) {
-        m_cornerRadiusX = radius;
-        updatePath(size());
-        updateHandles();
-    }
+    radius = qBound(0.0, radius, 100.0);
+    m_cornerRadiusX = radius;
+    updatePath(size());
+    updateHandles();
 }
 
 qreal RectangleShape::cornerRadiusY() const
@@ -314,11 +313,10 @@ qreal RectangleShape::cornerRadiusY() const
 
 void RectangleShape::setCornerRadiusY(qreal radius)
 {
-    if (radius >= 0.0 && radius <= 100.0) {
-        m_cornerRadiusY = radius;
-        updatePath(size());
-        updateHandles();
-    }
+    radius = qBound(0.0, radius, 100.0);
+    m_cornerRadiusY = radius;
+    updatePath(size());
+    updateHandles();
 }
 
 QString RectangleShape::pathShapeId() const
diff --git a/plugins/flake/pathshapes/rectangle/RectangleShapeFactory.cpp b/plugins/flake/pathshapes/rectangle/RectangleShapeFactory.cpp
index 7a5538670ae..a518a0625a0 100644
--- a/plugins/flake/pathshapes/rectangle/RectangleShapeFactory.cpp
+++ b/plugins/flake/pathshapes/rectangle/RectangleShapeFactory.cpp
@@ -25,6 +25,8 @@
 #include <KoXmlReader.h>
 #include <KoGradientBackground.h>
 #include <KoShapeLoadingContext.h>
+#include <KoProperties.h>
+#include "kis_assert.h"
 
 #include <KoIcon.h>
 #include <klocalizedstring.h>
@@ -62,6 +64,28 @@ KoShape *RectangleShapeFactory::createDefaultShape(KoDocumentResourceManager *)
     return rect;
 }
 
+KoShape *RectangleShapeFactory::createShape(const KoProperties *params, KoDocumentResourceManager *documentResources) const
+{
+    KoShape *shape = createDefaultShape(documentResources);
+    RectangleShape *rectShape = dynamic_cast<RectangleShape*>(shape);
+    KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(rectShape, shape);
+
+    rectShape->setSize(
+        QSizeF(params->doubleProperty("width", rectShape->size().width()),
+               params->doubleProperty("height", rectShape->size().height())));
+
+    rectShape->setAbsolutePosition(
+        QPointF(params->doubleProperty("x", rectShape->absolutePosition(KoFlake::TopLeft).x()),
+                params->doubleProperty("y", rectShape->absolutePosition(KoFlake::TopLeft).y())),
+        KoFlake::TopLeft);
+
+
+    rectShape->setCornerRadiusX(params->doubleProperty("rx", 0.0));
+    rectShape->setCornerRadiusY(params->doubleProperty("ry", 0.0));
+
+    return shape;
+}
+
 bool RectangleShapeFactory::supports(const KoXmlElement &e, KoShapeLoadingContext &/*context*/) const
 {
     Q_UNUSED(e);
diff --git a/plugins/flake/pathshapes/rectangle/RectangleShapeFactory.h b/plugins/flake/pathshapes/rectangle/RectangleShapeFactory.h
index 2e9aebcfa43..360813514c1 100644
--- a/plugins/flake/pathshapes/rectangle/RectangleShapeFactory.h
+++ b/plugins/flake/pathshapes/rectangle/RectangleShapeFactory.h
@@ -32,6 +32,8 @@ public:
     RectangleShapeFactory();
     ~RectangleShapeFactory() override {}
     KoShape *createDefaultShape(KoDocumentResourceManager *documentResources = 0) const override;
+    KoShape *createShape(const KoProperties *params, KoDocumentResourceManager *documentResources = 0) const override;
+
     bool supports(const KoXmlElement &e, KoShapeLoadingContext &context) const override;
     QList<KoShapeConfigWidgetBase *> createShapeOptionPanels() override;
 };
diff --git a/plugins/tools/basictools/kis_tool_ellipse.cc b/plugins/tools/basictools/kis_tool_ellipse.cc
index 92ef3c6b0f3..812f3ed8a01 100644
--- a/plugins/tools/basictools/kis_tool_ellipse.cc
+++ b/plugins/tools/basictools/kis_tool_ellipse.cc
@@ -49,8 +49,11 @@ void KisToolEllipse::resetCursorStyle()
     overrideCursorIfNotEditable();
 }
 
-void KisToolEllipse::finishRect(const QRectF& rect)
+void KisToolEllipse::finishRect(const QRectF& rect, qreal roundCornersX, qreal roundCornersY)
 {
+    Q_UNUSED(roundCornersX);
+    Q_UNUSED(roundCornersY);
+
     if (rect.isEmpty() || !blockUntilOperationsFinished())
         return;
 
diff --git a/plugins/tools/basictools/kis_tool_ellipse.h b/plugins/tools/basictools/kis_tool_ellipse.h
index 70c83f34cb1..f655aa662cb 100644
--- a/plugins/tools/basictools/kis_tool_ellipse.h
+++ b/plugins/tools/basictools/kis_tool_ellipse.h
@@ -46,7 +46,7 @@ protected Q_SLOTS:
     void resetCursorStyle() override;
 
 protected:
-    void finishRect(const QRectF& rect) override;
+    void finishRect(const QRectF& rect, qreal roundCornersX, qreal roundCornersY) override;
 };
 
 class KisToolEllipseFactory : public KoToolFactoryBase
diff --git a/plugins/tools/basictools/kis_tool_rectangle.cc b/plugins/tools/basictools/kis_tool_rectangle.cc
index d11c5a678a4..fadc347dcb5 100644
--- a/plugins/tools/basictools/kis_tool_rectangle.cc
+++ b/plugins/tools/basictools/kis_tool_rectangle.cc
@@ -53,7 +53,7 @@ void KisToolRectangle::resetCursorStyle()
     overrideCursorIfNotEditable();
 }
 
-void KisToolRectangle::finishRect(const QRectF &rect)
+void KisToolRectangle::finishRect(const QRectF &rect, qreal roundCornersX, qreal roundCornersY)
 {
     if (rect.isNull() || !blockUntilOperationsFinished())
         return;
@@ -68,10 +68,21 @@ void KisToolRectangle::finishRect(const QRectF &rect)
                                            canvas()->resourceManager(),
                                            strokeStyle(),
                                            fillStyle());
-        helper.paintRect(rect);
+
+        QPainterPath path;
+
+        if (roundCornersX > 0 || roundCornersY > 0) {
+            path.addRoundedRect(rect, roundCornersX, roundCornersY);
+        } else {
+            path.addRect(rect);
+        }
+
+        helper.paintPainterPath(path);
     } else {
-        QRectF r = convertToPt(rect);
-        KoShape* shape = KisShapeToolHelper::createRectangleShape(r);
+        const QRectF r = convertToPt(rect);
+        const qreal docRoundCornersX = convertToPt(roundCornersX);
+        const qreal docRoundCornersY = convertToPt(roundCornersY);
+        KoShape* shape = KisShapeToolHelper::createRectangleShape(r, docRoundCornersX, docRoundCornersY);
 
         KoShapeStrokeSP border;
         if (strokeStyle() == KisPainter::StrokeStyleBrush) {
diff --git a/plugins/tools/basictools/kis_tool_rectangle.h b/plugins/tools/basictools/kis_tool_rectangle.h
index 754483cd636..5798e8841c4 100644
--- a/plugins/tools/basictools/kis_tool_rectangle.h
+++ b/plugins/tools/basictools/kis_tool_rectangle.h
@@ -45,7 +45,7 @@ public:
     ~KisToolRectangle() override;
 
 protected:
-    void finishRect(const QRectF& rect) override;
+    void finishRect(const QRectF& rect, qreal roundCornersX, qreal roundCornersY) override;
 
 protected Q_SLOTS:
     void resetCursorStyle() override;
diff --git a/plugins/tools/selectiontools/kis_tool_select_elliptical.cc b/plugins/tools/selectiontools/kis_tool_select_elliptical.cc
index df26677de96..d925bfe624f 100644
--- a/plugins/tools/selectiontools/kis_tool_select_elliptical.cc
+++ b/plugins/tools/selectiontools/kis_tool_select_elliptical.cc
@@ -41,8 +41,11 @@ __KisToolSelectEllipticalLocal::__KisToolSelectEllipticalLocal(KoCanvasBase *can
     setObjectName("tool_select_elliptical");
 }
 
-void __KisToolSelectEllipticalLocal::finishRect(const QRectF &rect)
+void __KisToolSelectEllipticalLocal::finishRect(const QRectF &rect, qreal roundCornersX, qreal roundCornersY)
 {
+    Q_UNUSED(roundCornersX);
+    Q_UNUSED(roundCornersY);
+
     KisCanvas2 * kisCanvas = dynamic_cast<KisCanvas2*>(canvas());
     Q_ASSERT(kisCanvas);
 
diff --git a/plugins/tools/selectiontools/kis_tool_select_elliptical.h b/plugins/tools/selectiontools/kis_tool_select_elliptical.h
index c2ba6ece972..e06b938d845 100644
--- a/plugins/tools/selectiontools/kis_tool_select_elliptical.h
+++ b/plugins/tools/selectiontools/kis_tool_select_elliptical.h
@@ -46,7 +46,7 @@ protected:
     virtual SelectionAction selectionAction() const = 0;
     virtual bool antiAliasSelection() const = 0;
 private:
-    void finishRect(const QRectF &rect) override;
+    void finishRect(const QRectF &rect, qreal roundCornersX, qreal roundCornersY) override;
 
 
 
diff --git a/plugins/tools/selectiontools/kis_tool_select_rectangular.cc b/plugins/tools/selectiontools/kis_tool_select_rectangular.cc
index e38b9346e0b..b6257f83b69 100644
--- a/plugins/tools/selectiontools/kis_tool_select_rectangular.cc
+++ b/plugins/tools/selectiontools/kis_tool_select_rectangular.cc
@@ -42,7 +42,7 @@ __KisToolSelectRectangularLocal::__KisToolSelectRectangularLocal(KoCanvasBase *
         setObjectName("tool_select_rectangular");
 }
 
-void __KisToolSelectRectangularLocal::finishRect(const QRectF& rect)
+void __KisToolSelectRectangularLocal::finishRect(const QRectF& rect, qreal roundCornersX, qreal roundCornersY)
 {
     KisCanvas2 * kisCanvas = dynamic_cast<KisCanvas2*>(canvas());
     if (!kisCanvas)
@@ -66,14 +66,23 @@ void __KisToolSelectRectangularLocal::finishRect(const QRectF& rect)
             tmpSel->select(rc);
 
             QPainterPath cache;
-            cache.addRect(rc);
+
+            if (roundCornersX > 0 || roundCornersY > 0) {
+                cache.addRoundedRect(rc, roundCornersX, roundCornersY);
+            } else {
+                cache.addRect(rc);
+            }
+
             tmpSel->setOutlineCache(cache);
 
             helper.selectPixelSelection(tmpSel, selectionAction());
         }
     } else {
         QRectF documentRect = convertToPt(rc);
-        helper.addSelectionShape(KisShapeToolHelper::createRectangleShape(documentRect));
+        const qreal docRoundCornersX = convertToPt(roundCornersX);
+        const qreal docRoundCornersY = convertToPt(roundCornersY);
+
+        helper.addSelectionShape(KisShapeToolHelper::createRectangleShape(documentRect, docRoundCornersX, docRoundCornersY));
     }
 }
 
diff --git a/plugins/tools/selectiontools/kis_tool_select_rectangular.h b/plugins/tools/selectiontools/kis_tool_select_rectangular.h
index ecb33d5e3b5..4f3eda0cb25 100644
--- a/plugins/tools/selectiontools/kis_tool_select_rectangular.h
+++ b/plugins/tools/selectiontools/kis_tool_select_rectangular.h
@@ -43,7 +43,7 @@ protected:
     virtual SelectionAction selectionAction() const = 0;
 
 private:
-    void finishRect(const QRectF& rect) override;
+    void finishRect(const QRectF& rect, qreal roundCornersX, qreal roundCornersY) override;
 };
 
 


More information about the kimageshop mailing list