File indexing completed on 2024-12-22 04:16:47
0001 /* 0002 * KDE. Krita Project. 0003 * 0004 * SPDX-FileCopyrightText: 2022 Deif Lou <ginoba@gmail.com> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include <kis_cursor.h> 0010 #include <KoPathShape.h> 0011 #include <KisViewManager.h> 0012 #include <canvas/kis_canvas2.h> 0013 #include <kis_canvas_resource_provider.h> 0014 #include <KoIcon.h> 0015 0016 #include "KisPathEnclosingProducer.h" 0017 0018 KisToolPathLocalTool::KisToolPathLocalTool(KoCanvasBase * canvas, KisPathEnclosingProducer* parentTool) 0019 : KoCreatePathTool(canvas) 0020 , m_parentTool(parentTool) 0021 {} 0022 0023 void KisToolPathLocalTool::paintPath(KoPathShape &pathShape, QPainter &painter, const KoViewConverter &converter) 0024 { 0025 Q_UNUSED(converter); 0026 0027 QTransform matrix; 0028 matrix.scale(m_parentTool->image()->xRes(), m_parentTool->image()->yRes()); 0029 matrix.translate(pathShape.position().x(), pathShape.position().y()); 0030 m_parentTool->paintToolOutline(&painter, m_parentTool->pixelToView(matrix.map(pathShape.outline()))); 0031 } 0032 0033 void KisToolPathLocalTool::addPathShape(KoPathShape* pathShape) 0034 { 0035 m_parentTool->addPathShape(pathShape); 0036 } 0037 0038 void KisToolPathLocalTool::beginShape() 0039 { 0040 m_parentTool->beginShape(); 0041 } 0042 0043 void KisToolPathLocalTool::endShape() 0044 { 0045 m_parentTool->endShape(); 0046 } 0047 0048 KisPathEnclosingProducer::KisPathEnclosingProducer(KoCanvasBase * canvas) 0049 : KisDynamicDelegateTool<DelegatedPathTool>(canvas, 0050 KisCursor::load("tool_polygonal_selection_cursor.png", 6, 6), 0051 new KisToolPathLocalTool(canvas, this)) 0052 { 0053 setObjectName("enclosing_tool_path"); 0054 setSupportOutline(true); 0055 setOutlineEnabled(false); 0056 0057 KisCanvas2 *kritaCanvas = dynamic_cast<KisCanvas2*>(canvas); 0058 0059 connect(kritaCanvas->viewManager()->canvasResourceProvider(), SIGNAL(sigEffectiveCompositeOpChanged()), SLOT(resetCursorStyle())); 0060 } 0061 0062 KisPathEnclosingProducer::~KisPathEnclosingProducer() 0063 {} 0064 0065 void KisPathEnclosingProducer::resetCursorStyle() 0066 { 0067 if (isEraser()) { 0068 useCursor(KisCursor::load("tool_polygonal_selection_enclose_eraser_cursor.png", 6, 6)); 0069 } else { 0070 KisDynamicDelegateTool::resetCursorStyle(); 0071 } 0072 0073 overrideCursorIfNotEditable(); 0074 } 0075 0076 void KisPathEnclosingProducer::requestStrokeEnd() 0077 { 0078 KisDynamicDelegateTool::requestStrokeEnd(); 0079 localTool()->endPathWithoutLastPoint(); 0080 } 0081 0082 void KisPathEnclosingProducer::requestStrokeCancellation() 0083 { 0084 KisDynamicDelegateTool::requestStrokeCancellation(); 0085 localTool()->cancelPath(); 0086 } 0087 0088 KisPopupWidgetInterface* ::KisPathEnclosingProducer::popupWidget() 0089 { 0090 return m_hasUserInteractionRunning ? nullptr : KisDynamicDelegateTool::popupWidget(); 0091 } 0092 0093 void KisPathEnclosingProducer::mousePressEvent(KoPointerEvent *event) 0094 { 0095 Q_UNUSED(event) 0096 } 0097 0098 // Install an event filter to catch right-click events. 0099 // The simplest way to accommodate the popup palette binding. 0100 // This code is duplicated in kis_tool_select_path.cc 0101 bool KisPathEnclosingProducer::eventFilter(QObject *obj, QEvent *event) 0102 { 0103 Q_UNUSED(obj); 0104 if (!m_hasUserInteractionRunning) { 0105 return false; 0106 } 0107 if (event->type() == QEvent::MouseButtonPress || 0108 event->type() == QEvent::MouseButtonDblClick) { 0109 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event); 0110 if (mouseEvent->button() == Qt::RightButton) { 0111 localTool()->removeLastPoint(); 0112 return true; 0113 } 0114 } else if (event->type() == QEvent::TabletPress) { 0115 QTabletEvent *tabletEvent = static_cast<QTabletEvent*>(event); 0116 if (tabletEvent->button() == Qt::RightButton) { 0117 localTool()->removeLastPoint(); 0118 return true; 0119 } 0120 } 0121 return false; 0122 } 0123 0124 void KisPathEnclosingProducer::beginAlternateAction(KoPointerEvent *event, AlternateAction action) { 0125 KisDynamicDelegateTool::beginAlternateAction(event, action); 0126 if (!nodeEditable()) return; 0127 0128 if (nodePaintAbility() == KisDynamicDelegateTool::MYPAINTBRUSH_UNPAINTABLE) { 0129 KisCanvas2 * kiscanvas = static_cast<KisCanvas2*>(canvas()); 0130 QString message = i18n("The MyPaint Brush Engine is not available for this colorspace"); 0131 kiscanvas->viewManager()->showFloatingMessage(message, koIcon("object-locked")); 0132 event->ignore(); 0133 return; 0134 } 0135 } 0136 0137 void KisPathEnclosingProducer::beginPrimaryAction(KoPointerEvent* event) 0138 { 0139 if (!nodeEditable()) return; 0140 KisDynamicDelegateTool::mousePressEvent(event); 0141 } 0142 0143 void KisPathEnclosingProducer::continuePrimaryAction(KoPointerEvent *event) 0144 { 0145 mouseMoveEvent(event); 0146 } 0147 0148 void KisPathEnclosingProducer::endPrimaryAction(KoPointerEvent *event) 0149 { 0150 mouseReleaseEvent(event); 0151 } 0152 0153 void KisPathEnclosingProducer::beginPrimaryDoubleClickAction(KoPointerEvent *event) 0154 { 0155 KisDynamicDelegateTool::mouseDoubleClickEvent(event); 0156 } 0157 0158 void KisPathEnclosingProducer::addPathShape(KoPathShape* pathShape) 0159 { 0160 KisCanvas2 * kisCanvas = dynamic_cast<KisCanvas2*>(canvas()); 0161 if (!kisCanvas) { 0162 return; 0163 } 0164 0165 KisImageWSP image = kisCanvas->image(); 0166 KisPixelSelectionSP enclosingMask = new KisPixelSelection(); 0167 0168 pathShape->normalize(); 0169 pathShape->close(); 0170 0171 KisPainter painter(enclosingMask); 0172 painter.setPaintColor(KoColor(Qt::white, enclosingMask->colorSpace())); 0173 painter.setAntiAliasPolygonFill(false); 0174 painter.setFillStyle(KisPainter::FillStyleForegroundColor); 0175 painter.setStrokeStyle(KisPainter::StrokeStyleNone); 0176 0177 QTransform matrix; 0178 matrix.scale(image->xRes(), image->yRes()); 0179 matrix.translate(pathShape->position().x(), pathShape->position().y()); 0180 0181 QPainterPath path = matrix.map(pathShape->outline()); 0182 painter.fillPainterPath(path); 0183 enclosingMask->setOutlineCache(path); 0184 0185 delete pathShape; 0186 0187 emit enclosingMaskProduced(enclosingMask); 0188 } 0189 0190 bool KisPathEnclosingProducer::hasUserInteractionRunning() const 0191 { 0192 return m_hasUserInteractionRunning; 0193 } 0194 0195 void KisPathEnclosingProducer::beginShape() 0196 { 0197 m_hasUserInteractionRunning = true; 0198 } 0199 0200 void KisPathEnclosingProducer::endShape() 0201 { 0202 m_hasUserInteractionRunning = false; 0203 }