File indexing completed on 2024-12-22 04:16:38
0001 /* 0002 * kis_tool_select_polygonal.h - part of Krayon^WKrita 0003 * 0004 * SPDX-FileCopyrightText: 2000 John Califf <jcaliff@compuzone.net> 0005 * SPDX-FileCopyrightText: 2002 Patrick Julien <freak@codepimps.org> 0006 * SPDX-FileCopyrightText: 2004 Boudewijn Rempt <boud@valdyas.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_polygonal.h" 0014 0015 #include <KoPathShape.h> 0016 0017 #include "kis_algebra_2d.h" 0018 #include "kis_painter.h" 0019 #include <brushengine/kis_paintop_registry.h> 0020 #include "kis_selection_options.h" 0021 #include "kis_canvas2.h" 0022 #include "kis_pixel_selection.h" 0023 #include "kis_selection_tool_helper.h" 0024 #include "kis_shape_tool_helper.h" 0025 #include <kis_default_bounds.h> 0026 0027 #include "KisViewManager.h" 0028 #include "kis_selection_manager.h" 0029 #include <kis_command_utils.h> 0030 #include <kis_selection_filters.h> 0031 0032 __KisToolSelectPolygonalLocal::__KisToolSelectPolygonalLocal(KoCanvasBase *canvas) 0033 : KisToolPolylineBase(canvas, KisToolPolylineBase::SELECT, 0034 KisCursor::load("tool_polygonal_selection_cursor.png", 6, 6)) 0035 { 0036 setObjectName("tool_select_polygonal"); 0037 } 0038 0039 0040 KisToolSelectPolygonal::KisToolSelectPolygonal(KoCanvasBase *canvas): 0041 KisToolSelectBase<__KisToolSelectPolygonalLocal>(canvas, i18n("Polygonal Selection")) 0042 { 0043 } 0044 0045 void KisToolSelectPolygonal::finishPolyline(const QVector<QPointF> &points) 0046 { 0047 KisCanvas2 * kisCanvas = dynamic_cast<KisCanvas2*>(canvas()); 0048 Q_ASSERT(kisCanvas); 0049 if (!kisCanvas) 0050 return; 0051 0052 const QRectF boundingViewRect = pixelToView(KisAlgebra2D::accumulateBounds(points)); 0053 0054 KisSelectionToolHelper helper(kisCanvas, kundo2_i18n("Select Polygon")); 0055 0056 if (helper.tryDeselectCurrentSelection(pixelToView(boundingViewRect), selectionAction())) { 0057 return; 0058 } 0059 0060 const SelectionMode mode = 0061 helper.tryOverrideSelectionMode(kisCanvas->viewManager()->selection(), 0062 selectionMode(), 0063 selectionAction()); 0064 0065 if (mode == PIXEL_SELECTION) { 0066 KisProcessingApplicator applicator(currentImage(), 0067 currentNode(), 0068 KisProcessingApplicator::NONE, 0069 KisImageSignalVector(), 0070 kundo2_i18n("Select Polygon")); 0071 0072 KisPixelSelectionSP tmpSel = 0073 new KisPixelSelection(new KisDefaultBounds(currentImage())); 0074 0075 const bool antiAlias = antiAliasSelection(); 0076 const int grow = growSelection(); 0077 const int feather = featherSelection(); 0078 0079 QPainterPath path; 0080 path.addPolygon(points); 0081 path.closeSubpath(); 0082 0083 KUndo2Command *cmd = new KisCommandUtils::LambdaCommand( 0084 [tmpSel, antiAlias, grow, feather, path]() mutable 0085 -> KUndo2Command * { 0086 KisPainter painter(tmpSel); 0087 painter.setPaintColor(KoColor(Qt::black, tmpSel->colorSpace())); 0088 // Since the feathering already smooths the selection, the 0089 // antiAlias is not applied if we must feather 0090 painter.setAntiAliasPolygonFill(antiAlias && feather == 0); 0091 painter.setFillStyle(KisPainter::FillStyleForegroundColor); 0092 painter.setStrokeStyle(KisPainter::StrokeStyleNone); 0093 0094 painter.paintPainterPath(path); 0095 0096 if (grow > 0) { 0097 KisGrowSelectionFilter biggy(grow, grow); 0098 biggy.process(tmpSel, 0099 tmpSel->selectedRect().adjusted(-grow, 0100 -grow, 0101 grow, 0102 grow)); 0103 } else if (grow < 0) { 0104 KisShrinkSelectionFilter tiny(-grow, -grow, false); 0105 tiny.process(tmpSel, tmpSel->selectedRect()); 0106 } 0107 if (feather > 0) { 0108 KisFeatherSelectionFilter feathery(feather); 0109 feathery.process(tmpSel, 0110 tmpSel->selectedRect().adjusted(-feather, 0111 -feather, 0112 feather, 0113 feather)); 0114 } 0115 0116 if (grow == 0 && feather == 0) { 0117 tmpSel->setOutlineCache(path); 0118 } else { 0119 tmpSel->invalidateOutlineCache(); 0120 } 0121 0122 return 0; 0123 }); 0124 0125 applicator.applyCommand(cmd, KisStrokeJobData::SEQUENTIAL); 0126 helper.selectPixelSelection(applicator, tmpSel, selectionAction()); 0127 applicator.end(); 0128 0129 } else { 0130 KoPathShape* path = new KoPathShape(); 0131 path->setShapeId(KoPathShapeId); 0132 0133 QTransform resolutionMatrix; 0134 resolutionMatrix.scale(1 / currentImage()->xRes(), 1 / currentImage()->yRes()); 0135 path->moveTo(resolutionMatrix.map(points[0])); 0136 for (int i = 1; i < points.count(); i++) 0137 path->lineTo(resolutionMatrix.map(points[i])); 0138 path->close(); 0139 path->normalize(); 0140 0141 helper.addSelectionShape(path, selectionAction()); 0142 } 0143 } 0144 0145 void KisToolSelectPolygonal::beginShape() 0146 { 0147 beginSelectInteraction(); 0148 } 0149 0150 void KisToolSelectPolygonal::endShape() 0151 { 0152 endSelectInteraction(); 0153 } 0154 0155 void KisToolSelectPolygonal::resetCursorStyle() 0156 { 0157 if (selectionAction() == SELECTION_ADD) { 0158 useCursor(KisCursor::load("tool_polygonal_selection_cursor_add.png", 6, 6)); 0159 } else if (selectionAction() == SELECTION_SUBTRACT) { 0160 useCursor(KisCursor::load("tool_polygonal_selection_cursor_sub.png", 6, 6)); 0161 } else if (selectionAction() == SELECTION_INTERSECT) { 0162 useCursor(KisCursor::load("tool_polygonal_selection_cursor_inter.png", 6, 6)); 0163 } else if (selectionAction() == SELECTION_SYMMETRICDIFFERENCE) { 0164 useCursor(KisCursor::load("tool_polygonal_selection_cursor_symdiff.png", 6, 6)); 0165 } else { 0166 KisToolSelectBase<__KisToolSelectPolygonalLocal>::resetCursorStyle(); 0167 } 0168 } 0169