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