File indexing completed on 2024-05-26 04:34:30

0001 /*
0002  *  kis_tool_select_elliptical.cc -- part of Krita
0003  *
0004  *  SPDX-FileCopyrightText: 2004 Boudewijn Rempt (boud@valdyas.org)
0005  *  SPDX-FileCopyrightText: 2007 Sven Langkamp <sven.langkamp@gmail.com>
0006  *  SPDX-FileCopyrightText: 2015 Michael Abrahams <miabraha@gmail.com>
0007  *
0008  *  SPDX-License-Identifier: GPL-2.0-or-later
0009  */
0010 
0011 #include "kis_tool_select_elliptical.h"
0012 
0013 #include <QVBoxLayout>
0014 
0015 #include "KisViewManager.h"
0016 #include "kis_canvas2.h"
0017 #include "kis_painter.h"
0018 #include "kis_pixel_selection.h"
0019 #include "kis_selection_manager.h"
0020 #include "kis_selection_options.h"
0021 #include "kis_selection_tool_helper.h"
0022 #include "kis_shape_tool_helper.h"
0023 #include <brushengine/kis_paintop_registry.h>
0024 #include <kis_command_utils.h>
0025 #include <kis_selection_filters.h>
0026 #include <kis_default_bounds.h>
0027 
0028 __KisToolSelectEllipticalLocal::__KisToolSelectEllipticalLocal(KoCanvasBase *canvas)
0029     : KisToolEllipseBase(canvas, KisToolEllipseBase::SELECT,
0030                          KisCursor::load("tool_elliptical_selection_cursor.png", 6, 6))
0031 {
0032     setObjectName("tool_select_elliptical");
0033 }
0034 
0035 
0036 KisToolSelectElliptical::KisToolSelectElliptical(KoCanvasBase *canvas):
0037     KisToolSelectBase<__KisToolSelectEllipticalLocal>(canvas, i18n("Elliptical Selection"))
0038 {}
0039 
0040 void KisToolSelectElliptical::finishRect(const QRectF &rect, qreal roundCornersX, qreal roundCornersY)
0041 {
0042     Q_UNUSED(roundCornersX);
0043     Q_UNUSED(roundCornersY);
0044 
0045     KisCanvas2 * kisCanvas = dynamic_cast<KisCanvas2*>(canvas());
0046     Q_ASSERT(kisCanvas);
0047 
0048     KisSelectionToolHelper helper(kisCanvas, kundo2_i18n("Select Ellipse"));
0049 
0050     if (helper.tryDeselectCurrentSelection(pixelToView(rect), selectionAction())) {
0051         return;
0052     }
0053 
0054     const SelectionMode mode =
0055         helper.tryOverrideSelectionMode(kisCanvas->viewManager()->selection(),
0056                                         selectionMode(),
0057                                         selectionAction());
0058 
0059     if (mode == PIXEL_SELECTION) {
0060         KisProcessingApplicator applicator(currentImage(),
0061                                            currentNode(),
0062                                            KisProcessingApplicator::NONE,
0063                                            KisImageSignalVector(),
0064                                            kundo2_i18n("Select Ellipse"));
0065 
0066         KisPixelSelectionSP tmpSel =
0067             new KisPixelSelection(new KisDefaultBounds(currentImage()));
0068 
0069         const bool antiAlias = antiAliasSelection();
0070         const int grow = growSelection();
0071         const int feather = featherSelection();
0072 
0073         QPainterPath path;
0074         path.addEllipse(rect);
0075         getRotatedPath(path, rect.center(), getRotationAngle());
0076 
0077         KUndo2Command *cmd = new KisCommandUtils::LambdaCommand(
0078             [tmpSel, antiAlias, grow, feather, path]() mutable
0079             -> KUndo2Command * {
0080                 KisPainter painter(tmpSel);
0081                 painter.setPaintColor(KoColor(Qt::black, tmpSel->colorSpace()));
0082                 // Since the feathering already smooths the selection, the
0083                 // antiAlias is not applied if we must feather
0084                 painter.setAntiAliasPolygonFill(antiAlias && feather == 0);
0085                 painter.setFillStyle(KisPainter::FillStyleForegroundColor);
0086                 painter.setStrokeStyle(KisPainter::StrokeStyleNone);
0087 
0088                 painter.paintPainterPath(path);
0089 
0090                 if (grow > 0) {
0091                     KisGrowSelectionFilter biggy(grow, grow);
0092                     biggy.process(tmpSel,
0093                                   tmpSel->selectedRect().adjusted(-grow,
0094                                                                   -grow,
0095                                                                   grow,
0096                                                                   grow));
0097                 } else if (grow < 0) {
0098                     KisShrinkSelectionFilter tiny(-grow, -grow, false);
0099                     tiny.process(tmpSel, tmpSel->selectedRect());
0100                 }
0101                 if (feather > 0) {
0102                     KisFeatherSelectionFilter feathery(feather);
0103                     feathery.process(tmpSel,
0104                                      tmpSel->selectedRect().adjusted(-feather,
0105                                                                      -feather,
0106                                                                      feather,
0107                                                                      feather));
0108                 }
0109 
0110                 if (grow == 0 && feather == 0) {
0111                     tmpSel->setOutlineCache(path);
0112                 } else {
0113                     tmpSel->invalidateOutlineCache();
0114                 }
0115 
0116                 return 0;
0117             });
0118 
0119         applicator.applyCommand(cmd, KisStrokeJobData::SEQUENTIAL);
0120         helper.selectPixelSelection(applicator, tmpSel, selectionAction());
0121         applicator.end();
0122 
0123     } else {
0124         QRectF ptRect = convertToPt(rect);
0125         KoShape* shape = KisShapeToolHelper::createEllipseShape(ptRect);
0126         shape->rotate(qRadiansToDegrees(getRotationAngle()));
0127 
0128         helper.addSelectionShape(shape, selectionAction());
0129     }
0130 }
0131 
0132 void KisToolSelectElliptical::beginShape()
0133 {
0134     beginSelectInteraction();
0135 }
0136 
0137 void KisToolSelectElliptical::endShape()
0138 {
0139     endSelectInteraction();
0140 }
0141 
0142 void KisToolSelectElliptical::resetCursorStyle()
0143 {
0144     if (selectionAction() == SELECTION_ADD) {
0145         useCursor(KisCursor::load("tool_elliptical_selection_cursor_add.png", 6, 6));
0146     } else if (selectionAction() == SELECTION_SUBTRACT) {
0147         useCursor(KisCursor::load("tool_elliptical_selection_cursor_sub.png", 6, 6));
0148     } else if (selectionAction() == SELECTION_INTERSECT) {
0149         useCursor(KisCursor::load("tool_elliptical_selection_cursor_inter.png", 6, 6));
0150     } else if (selectionAction() == SELECTION_SYMMETRICDIFFERENCE) {
0151         useCursor(KisCursor::load("tool_elliptical_selection_cursor_symdiff.png", 6, 6));
0152     } else {
0153         KisToolSelectBase<__KisToolSelectEllipticalLocal>::resetCursorStyle();
0154     }
0155 }
0156