File indexing completed on 2024-05-12 04:21:25
0001 0002 /* 0003 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org> 0004 All rights reserved. 0005 0006 Redistribution and use in source and binary forms, with or without 0007 modification, are permitted provided that the following conditions 0008 are met: 0009 0010 1. Redistributions of source code must retain the above copyright 0011 notice, this list of conditions and the following disclaimer. 0012 2. Redistributions in binary form must reproduce the above copyright 0013 notice, this list of conditions and the following disclaimer in the 0014 documentation and/or other materials provided with the distribution. 0015 0016 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 0017 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 0018 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 0019 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 0020 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 0021 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0022 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0023 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0024 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 0025 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0026 */ 0027 0028 0029 #define DEBUG_KP_TOOL_SPRAYCAN 0 0030 0031 #include "kpToolSpraycan.h" 0032 0033 #include "kpDefs.h" 0034 #include "document/kpDocument.h" 0035 #include "imagelib/kpPainter.h" 0036 #include "pixmapfx/kpPixmapFX.h" 0037 #include "environments/tools/kpToolEnvironment.h" 0038 #include "commands/tools/flow/kpToolFlowCommand.h" 0039 #include "widgets/toolbars/kpToolToolBar.h" 0040 #include "widgets/toolbars/options/kpToolWidgetSpraycanSize.h" 0041 #include "views/kpView.h" 0042 #include "views/manager/kpViewManager.h" 0043 0044 #include <cstdlib> 0045 0046 #include "kpLogCategories.h" 0047 #include <KLocalizedString> 0048 0049 #include <QPoint> 0050 #include <QRect> 0051 #include <QTimer> 0052 0053 //--------------------------------------------------------------------- 0054 0055 kpToolSpraycan::kpToolSpraycan (kpToolEnvironment *environ, QObject *parent) 0056 : kpToolFlowBase (i18n ("Spraycan"), i18n ("Sprays graffiti"), 0057 Qt::Key_Y, 0058 environ, parent, QStringLiteral("tool_spraycan")), 0059 m_toolWidgetSpraycanSize(nullptr) 0060 { 0061 m_timer = new QTimer (this); 0062 m_timer->setInterval (25/*ms*/); 0063 connect (m_timer, &QTimer::timeout, this, &kpToolSpraycan::timeoutDraw); 0064 } 0065 0066 //--------------------------------------------------------------------- 0067 0068 // protected virtual [base kpToolFlowBase] 0069 QString kpToolSpraycan::haventBegunDrawUserMessage () const 0070 { 0071 return i18n ("Click or drag to spray graffiti."); 0072 } 0073 0074 //--------------------------------------------------------------------- 0075 0076 // public virtual [base kpToolFlowBase] 0077 void kpToolSpraycan::begin () 0078 { 0079 kpToolToolBar *tb = toolToolBar (); 0080 Q_ASSERT (tb); 0081 0082 m_toolWidgetSpraycanSize = tb->toolWidgetSpraycanSize (); 0083 connect (m_toolWidgetSpraycanSize, &kpToolWidgetSpraycanSize::spraycanSizeChanged, 0084 this, &kpToolSpraycan::slotSpraycanSizeChanged); 0085 m_toolWidgetSpraycanSize->show (); 0086 0087 kpToolFlowBase::begin (); 0088 } 0089 0090 // public virtual [base kpToolFlowBase] 0091 void kpToolSpraycan::end () 0092 { 0093 kpToolFlowBase::end (); 0094 0095 disconnect (m_toolWidgetSpraycanSize, &kpToolWidgetSpraycanSize::spraycanSizeChanged, 0096 this, &kpToolSpraycan::slotSpraycanSizeChanged); 0097 0098 m_toolWidgetSpraycanSize = nullptr; 0099 } 0100 0101 0102 // public virtual [base kpToolFlowBase] 0103 void kpToolSpraycan::beginDraw () 0104 { 0105 #if DEBUG_KP_TOOL_SPRAYCAN 0106 qCDebug(kpLogTools) << "kpToolSpraycan::beginDraw()"; 0107 #endif 0108 0109 kpToolFlowBase::beginDraw (); 0110 0111 // We draw even if the user doesn't move the mouse. 0112 // We still timeout-draw even if the user _does_ move the mouse. 0113 m_timer->start (); 0114 } 0115 0116 0117 // protected 0118 QRect kpToolSpraycan::drawLineWithProbability (const QPoint &thisPoint, 0119 const QPoint &lastPoint, 0120 double probability) 0121 { 0122 #if DEBUG_KP_TOOL_SPRAYCAN 0123 qCDebug(kpLogTools) << "CALL(thisPoint=" << thisPoint 0124 << ",lastPoint=" << lastPoint 0125 << ")"; 0126 #endif 0127 0128 QList <QPoint> docPoints = kpPainter::interpolatePoints (lastPoint, thisPoint, 0129 false/*no need for cardinally adjacency points*/, 0130 probability); 0131 #if DEBUG_KP_TOOL_SPRAYCAN 0132 qCDebug(kpLogTools) << "\tdocPoints=" << docPoints; 0133 #endif 0134 0135 0136 // By chance no points to draw? 0137 if (docPoints.empty ()) { 0138 return {}; 0139 } 0140 0141 0142 // For efficiency, only get image after NOP check above. 0143 QRect docRect = kpPainter::normalizedRect(thisPoint, lastPoint); 0144 docRect = neededRect (docRect, spraycanSize ()); 0145 kpImage image = document ()->getImageAt (docRect); 0146 0147 0148 // Spray at each point, onto the image. 0149 // 0150 // Note in passing: Unlike other tools such as the Brush, drawing 0151 // over the same point does result in a different 0152 // appearance. 0153 0154 QList <QPoint> imagePoints; 0155 for (const auto &dp : docPoints) 0156 imagePoints.append (dp - docRect.topLeft ()); 0157 0158 kpPainter::sprayPoints (&image, 0159 imagePoints, 0160 color (mouseButton ()), 0161 spraycanSize ()); 0162 0163 0164 viewManager ()->setFastUpdates (); 0165 document ()->setImageAt (image, docRect.topLeft ()); 0166 viewManager ()->restoreFastUpdates (); 0167 0168 0169 return docRect; 0170 } 0171 0172 // public virtual [base kpToolFlowBase] 0173 QRect kpToolSpraycan::drawPoint (const QPoint &point) 0174 { 0175 #if DEBUG_KP_TOOL_SPRAYCAN 0176 qCDebug(kpLogTools) << "kpToolSpraycan::drawPoint" << point 0177 << " lastPoint=" << lastPoint (); 0178 #endif 0179 0180 // If this is the first in the flow or if the user is moving the spray, 0181 // make the spray line continuous. 0182 if (point != lastPoint ()) 0183 { 0184 // Draw at this single point without delay. 0185 return drawLineWithProbability (point, point, 0186 1.0/*100% chance of drawing*/); 0187 } 0188 0189 return {}; 0190 } 0191 0192 // public virtual [base kpToolFlowBase] 0193 QRect kpToolSpraycan::drawLine (const QPoint &thisPoint, const QPoint &lastPoint) 0194 { 0195 #if DEBUG_KP_TOOL_SPRAYCAN 0196 qCDebug(kpLogTools) << "CALL(thisPoint=" << thisPoint << ",lastPoint=" << lastPoint; 0197 #endif 0198 0199 // Draw only every so often in response to movement. 0200 return drawLineWithProbability (thisPoint, lastPoint, 0201 0.05/*less dense: select 5% of adjacent pixels - not all*/); 0202 } 0203 0204 // protected slot 0205 void kpToolSpraycan::timeoutDraw () 0206 { 0207 #if DEBUG_KP_TOOL_SPRAYCAN 0208 qCDebug(kpLogTools) << "kpToolSpraycan::timeoutDraw()"; 0209 #endif 0210 0211 // Draw at this single point without delay. 0212 const QRect drawnRect = drawLineWithProbability (currentPoint (), currentPoint (), 0213 1.0/*100% chance of drawing*/); 0214 0215 // kpToolFlowBase() does this after calling drawPoint() and drawLine() so 0216 // we need to do it too. 0217 currentCommand ()->updateBoundingRect (drawnRect); 0218 } 0219 0220 0221 // public virtual [base kpToolFlowBase] 0222 void kpToolSpraycan::cancelShape () 0223 { 0224 #if DEBUG_KP_TOOL_SPRAYCAN 0225 qCDebug(kpLogTools) << "kpToolSpraycan::cancelShape()"; 0226 #endif 0227 0228 m_timer->stop (); 0229 kpToolFlowBase::cancelShape (); 0230 } 0231 0232 // public virtual [base kpToolFlowBase] 0233 void kpToolSpraycan::endDraw (const QPoint &thisPoint, 0234 const QRect &normalizedRect) 0235 { 0236 #if DEBUG_KP_TOOL_SPRAYCAN 0237 qCDebug(kpLogTools) << "kpToolSpraycan::endDraw(thisPoint=" << thisPoint 0238 << ")"; 0239 #endif 0240 0241 m_timer->stop (); 0242 kpToolFlowBase::endDraw (thisPoint, normalizedRect); 0243 } 0244 0245 0246 // protected 0247 int kpToolSpraycan::spraycanSize () const 0248 { 0249 return m_toolWidgetSpraycanSize->spraycanSize (); 0250 } 0251 0252 // protected slot 0253 void kpToolSpraycan::slotSpraycanSizeChanged (int size) 0254 { 0255 (void) size; 0256 } 0257 0258 #include "moc_kpToolSpraycan.cpp"