File indexing completed on 2024-12-22 04:16:38

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