File indexing completed on 2024-12-15 04:03:31

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_WIDGET_BRUSH 0
0030 
0031 
0032 #include "widgets/toolbars/options/kpToolWidgetBrush.h"
0033 
0034 #include <QPainter>
0035 
0036 #include <KLocalizedString>
0037 
0038 #include "kpLogCategories.h"
0039 #include "kpDefs.h"
0040 
0041 //---------------------------------------------------------------------
0042 
0043 // LOREFACTOR: more OO, no arrays (use safer structs).
0044 /* sync: <brushes> */
0045 static int BrushSizes [][3] =
0046 {
0047     {8, 4, 1/*like Pen*/},
0048     {9, 5, 2},
0049     {9, 5, 2},
0050     {9, 5, 2}
0051 };
0052 
0053 #define BRUSH_SIZE_NUM_COLS (int (sizeof (::BrushSizes [0]) / sizeof (::BrushSizes [0][0])))
0054 #define BRUSH_SIZE_NUM_ROWS (int (sizeof (::BrushSizes) / sizeof (::BrushSizes [0])))
0055 
0056 
0057 //---------------------------------------------------------------------
0058 
0059 static void Draw (kpImage *destImage, const QPoint &topLeft, void *userData)
0060 {
0061     auto *pack = static_cast <kpToolWidgetBrush::DrawPackage *> (userData);
0062 
0063 #if DEBUG_KP_TOOL_WIDGET_BRUSH
0064     qCDebug(kpLogWidgets) << "kptoolwidgetbrush.cpp:Draw(destImage,topLeft="
0065               << topLeft << " pack: row=" << pack->row << " col=" << pack->col
0066               << " color=" << (int *) pack->color.toQRgb ();
0067 #endif
0068     const int size = ::BrushSizes [pack->row][pack->col];
0069 #if DEBUG_KP_TOOL_WIDGET_BRUSH
0070     qCDebug(kpLogWidgets) << "\tsize=" << size;
0071 #endif
0072 
0073     QPainter painter(destImage);
0074 
0075     if ( size == 1 )
0076     {
0077       painter.setPen(pack->color.toQColor());
0078       painter.drawPoint(topLeft);
0079       return;
0080     }
0081 
0082     // sync: <brushes>
0083     switch (pack->row/*shape*/)
0084     {
0085       case 0:
0086       {
0087         // work around ugly circle when using QPainter on QImage
0088         if ( size == 4 )
0089         {
0090           // do not draw a pixel twice, as with an alpha color it will become darker
0091           painter.setPen(Qt::NoPen);
0092           painter.setBrush(pack->color.toQColor());
0093           painter.drawRect(topLeft.x() + 1, topLeft.y(), 2, size);
0094           painter.setPen(pack->color.toQColor());
0095           painter.drawLine(topLeft.x(), topLeft.y() + 1, topLeft.x(), topLeft.y() + 2);
0096           painter.drawLine(topLeft.x() + 3, topLeft.y() + 1, topLeft.x() + 3, topLeft.y() + 2);
0097         }
0098         else if ( size == 8 )  // size defined in BrushSizes above
0099         {
0100           // do not draw a pixel twice, as with an alpha color it will become darker
0101           painter.setPen(Qt::NoPen);
0102           painter.setBrush(pack->color.toQColor());
0103           painter.drawRect(topLeft.x() + 2, topLeft.y(), 4, size);
0104           painter.drawRect(topLeft.x(), topLeft.y() + 2, 2, 4);
0105           painter.drawRect(topLeft.x() + 6, topLeft.y() + 2, 2, 4);
0106           painter.setPen(pack->color.toQColor());
0107           painter.drawPoint(topLeft.x() + 1, topLeft.y() + 1);
0108           painter.drawPoint(topLeft.x() + 6, topLeft.y() + 1);
0109           painter.drawPoint(topLeft.x() + 1, topLeft.y() + 6);
0110           painter.drawPoint(topLeft.x() + 6, topLeft.y() + 6);
0111         }
0112         else
0113         {
0114           Q_ASSERT(!"illegal size");
0115         }
0116         break;
0117       }
0118 
0119       case 1:
0120       {
0121         // only paint filling so that a color with an alpha channel does not
0122         // create a darker border due to drawing some pixels twice with composition
0123         painter.setPen(Qt::NoPen);
0124         painter.setBrush(pack->color.toQColor());
0125         painter.drawRect(topLeft.x(), topLeft.y(), size, size);
0126         break;
0127       }
0128 
0129       case 2:
0130       {
0131         painter.setPen(pack->color.toQColor());
0132         painter.drawLine(topLeft.x() + size - 1, topLeft.y(),
0133                          topLeft.x(), topLeft.y() + size - 1);
0134         break;
0135       }
0136 
0137       case 3:
0138       {
0139         painter.setPen(pack->color.toQColor());
0140         painter.drawLine(topLeft.x(), topLeft.y(),
0141                          topLeft.x() + size - 1, topLeft.y() + size - 1);
0142         break;
0143       }
0144 
0145     default:
0146         Q_ASSERT (!"Unknown row");
0147         break;
0148     }
0149 }
0150 
0151 //---------------------------------------------------------------------
0152 
0153 kpToolWidgetBrush::kpToolWidgetBrush (QWidget *parent, const QString &name)
0154     : kpToolWidgetBase (parent, name)
0155 {
0156     for (int shape = 0; shape < BRUSH_SIZE_NUM_ROWS; shape++)
0157     {
0158         for (int i = 0; i < BRUSH_SIZE_NUM_COLS; i++)
0159         {
0160             const int s = ::BrushSizes [shape][i];
0161 
0162 
0163             const int w = (width () - 2/*margin*/ - 2/*spacing*/)
0164                 / BRUSH_SIZE_NUM_COLS;
0165             const int h = (height () - 2/*margin*/ - 3/*spacing*/)
0166                 / BRUSH_SIZE_NUM_ROWS;
0167             Q_ASSERT (w >= s && h >= s);
0168             QImage previewPixmap (w, h, QImage::Format_ARGB32_Premultiplied);
0169             previewPixmap.fill(0);
0170 
0171             DrawPackage pack = drawFunctionDataForRowCol (kpColor::Black, shape, i);
0172             ::Draw (&previewPixmap,
0173                 QPoint ((previewPixmap.width () - s) / 2,
0174                         (previewPixmap.height () - s) / 2),
0175                 &pack);
0176 
0177             addOption(QPixmap::fromImage(std::move(previewPixmap)),
0178                       brushName(shape, i) /*tooltip*/);
0179         }
0180 
0181         startNewOptionRow ();
0182     }
0183 
0184     finishConstruction (0, 0);
0185 }
0186 
0187 //---------------------------------------------------------------------
0188 
0189 kpToolWidgetBrush::~kpToolWidgetBrush () = default;
0190 
0191 //---------------------------------------------------------------------
0192 
0193 // private
0194 QString kpToolWidgetBrush::brushName (int shape, int whichSize) const
0195 {
0196     int s = ::BrushSizes [shape][whichSize];
0197 
0198     if (s == 1) {
0199         return i18n ("1x1");
0200     }
0201 
0202     QString shapeName;
0203 
0204     // sync: <brushes>
0205     switch (shape)
0206     {
0207     case 0:
0208         shapeName = i18n ("Circle");
0209         break;
0210     case 1:
0211         shapeName = i18n ("Square");
0212         break;
0213     case 2:
0214         // TODO: is this really the name of a shape? :)
0215         shapeName = i18n ("Slash");
0216         break;
0217     case 3:
0218         // TODO: is this really the name of a shape? :)
0219         shapeName = i18n ("Backslash");
0220         break;
0221     }
0222 
0223     if (shapeName.isEmpty ()) {
0224         return {};
0225     }
0226 
0227     return i18n ("%1x%2 %3", s, s, shapeName);
0228 }
0229 
0230 //---------------------------------------------------------------------
0231 
0232 // public
0233 int kpToolWidgetBrush::brushSize () const
0234 {
0235     return ::BrushSizes [selectedRow ()][selectedCol ()];
0236 }
0237 
0238 //---------------------------------------------------------------------
0239 
0240 // public
0241 bool kpToolWidgetBrush::brushIsDiagonalLine () const
0242 {
0243     // sync: <brushes>
0244     return (selectedRow () >= 2);
0245 }
0246 
0247 //---------------------------------------------------------------------
0248 
0249 
0250 // public
0251 kpTempImage::UserFunctionType kpToolWidgetBrush::drawFunction () const
0252 {
0253     return &::Draw;
0254 }
0255 
0256 //---------------------------------------------------------------------
0257 
0258 
0259 // public static
0260 kpToolWidgetBrush::DrawPackage kpToolWidgetBrush::drawFunctionDataForRowCol (
0261         const kpColor &color, int row, int col)
0262 {
0263     Q_ASSERT (row >= 0 && col >= 0);
0264 
0265     DrawPackage pack;
0266 
0267     pack.row = row;
0268     pack.col = col;
0269     pack.color = color;
0270 
0271     return pack;
0272 }
0273 
0274 //---------------------------------------------------------------------
0275 
0276 // public
0277 kpToolWidgetBrush::DrawPackage kpToolWidgetBrush::drawFunctionData (
0278         const kpColor &color) const
0279 {
0280     return drawFunctionDataForRowCol (color, selectedRow (), selectedCol ());
0281 }
0282 
0283 //---------------------------------------------------------------------
0284 
0285 // protected slot virtual [base kpToolWidgetBase]
0286 bool kpToolWidgetBrush::setSelected (int row, int col, bool saveAsDefault)
0287 {
0288     const bool ret = kpToolWidgetBase::setSelected (row, col, saveAsDefault);
0289     if (ret) {
0290         Q_EMIT brushChanged ();
0291     }
0292     return ret;
0293 }
0294 
0295 //---------------------------------------------------------------------
0296 
0297 #include "moc_kpToolWidgetBrush.cpp"