File indexing completed on 2024-05-12 04:21:25

0001 /*
0002    Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
0003    Copyright (c) 2017      Martin Koller <kollix@aon.at>
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_CURVE 0
0030 
0031 
0032 #include "kpToolCurve.h"
0033 #include "kpLogCategories.h"
0034 #include "environments/tools/kpToolEnvironment.h"
0035 #include "pixmapfx/kpPixmapFX.h"
0036 
0037 #include <QPainter>
0038 #include <QPen>
0039 #include <QPainterPath>
0040 
0041 #include <KLocalizedString>
0042 
0043 //--------------------------------------------------------------------------------
0044 
0045 static void DrawCurveShape (kpImage *image,
0046         const QPolygon &points,
0047         const kpColor &fcolor, int penWidth,
0048         const kpColor &bcolor,
0049         bool isFinal)
0050 {
0051     (void) bcolor;
0052     (void) isFinal;
0053 
0054     Q_ASSERT (points.count () >= 2 && points.count () <= 4);
0055 
0056     const QPoint startPoint = points [0];
0057     const QPoint endPoint = points [1];
0058 
0059     QPoint controlPointP, controlPointQ;
0060 
0061     switch (points.count ())
0062     {
0063     // Just a line?
0064     case 2:
0065         controlPointP = startPoint;
0066         controlPointQ = endPoint;
0067         break;
0068 
0069     // Single control point?
0070     case 3:
0071         controlPointP = controlPointQ = points [2];
0072         break;
0073 
0074     // Two control points?
0075     case 4:
0076         controlPointP = points [2];
0077         controlPointQ = points [3];
0078         break;
0079     }
0080 
0081     QPainter painter(image);
0082     painter.setRenderHint(QPainter::Antialiasing, kpToolEnvironment::drawAntiAliased);
0083 
0084     painter.setPen(QPen(fcolor.toQColor(), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
0085 
0086     if ( kpPixmapFX::Only1PixelInPointArray(points) )
0087     {
0088       painter.drawPoint(points[0]);
0089       return;
0090     }
0091 
0092     QPainterPath curvePath;
0093     curvePath.moveTo(startPoint);
0094     curvePath.cubicTo(controlPointP, controlPointQ, endPoint);
0095 
0096     painter.strokePath(curvePath, painter.pen());
0097 }
0098 
0099 //--------------------------------------------------------------------------------
0100 
0101 kpToolCurve::kpToolCurve (kpToolEnvironment *environ, QObject *parent)
0102     : kpToolPolygonalBase (
0103         i18n ("Curve"),
0104         i18n ("Draws curves"),
0105         &::DrawCurveShape,
0106         Qt::Key_V,
0107         environ, parent,
0108         QStringLiteral("tool_curve"))
0109 {
0110 }
0111 
0112 kpToolCurve::~kpToolCurve () = default;
0113 
0114 
0115 // protected virtual [base kpToolPolygonalBase]
0116 QString kpToolCurve::haventBegunShapeUserMessage () const
0117 {
0118     return i18n ("Drag out the start and end points.");
0119 }
0120 
0121 
0122 // protected virtual [base kpToolPolygonalBase]
0123 bool kpToolCurve::drawingALine () const
0124 {
0125     // On the initial drag (consisting of 2 points) creates a line.
0126     // Future drags are for control points.
0127     return (points ()->count () == 2);
0128 }
0129 
0130 
0131 // public virtual [base kpTool]
0132 void kpToolCurve::endDraw (const QPoint &, const QRect &)
0133 {
0134 #if DEBUG_KP_TOOL_CURVE
0135     qCDebug(kpLogTools) << "kpToolCurve::endDraw()  points="
0136         << points ()->toList ();
0137 #endif
0138 
0139     switch (points ()->count ())
0140     {
0141     // A click of the other mouse button (to finish shape, instead of adding
0142     // another control point) would have caused endShape() to have been
0143     // called in kpToolPolygonalBase::beginDraw().  The points list would now
0144     // be empty.  We are being called by kpTool::mouseReleaseEvent().
0145     case 0:
0146         break;
0147 
0148     case 1:
0149         Q_ASSERT (!"kpToolPolygonalBase::beginDraw() ensures we have >= 2 ctrl points");
0150         break;
0151 
0152     // Just completed initial line?
0153     case 2:
0154         if (originatingMouseButton () == 0)
0155         {
0156             setUserMessage (
0157                 i18n ("Left drag to set the first control point or right click to finish."));
0158         }
0159         else
0160         {
0161             setUserMessage (
0162                 i18n ("Right drag to set the first control point or left click to finish."));
0163         }
0164 
0165         break;
0166 
0167     // Have initial line and first control point?
0168     case 3:
0169         if (originatingMouseButton () == 0)
0170         {
0171             setUserMessage (
0172                 i18n ("Left drag to set the last control point or right click to finish."));
0173         }
0174         else
0175         {
0176             setUserMessage (
0177                 i18n ("Right drag to set the last control point or left click to finish."));
0178         }
0179 
0180         break;
0181 
0182     // Have initial line and both control points?
0183     case 4:
0184     #if DEBUG_KP_TOOL_CURVE
0185         qCDebug(kpLogTools) << "\tending shape";
0186     #endif
0187         endShape ();
0188         break;
0189 
0190     default:
0191         Q_ASSERT (!"Impossible number of points");
0192         break;
0193     }
0194 }
0195 
0196 #include "moc_kpToolCurve.cpp"