krita

kis_gradient_painter.cc

00001 /*
00002  *  Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include <stdlib.h>
00020 #include <string.h>
00021 #include <cfloat>
00022 
00023 #include "qbrush.h"
00024 #include "qcolor.h"
00025 #include "qfontinfo.h"
00026 #include "qfontmetrics.h"
00027 #include "qpen.h"
00028 #include "qregion.h"
00029 #include "qwmatrix.h"
00030 #include <qimage.h>
00031 #include <qmap.h>
00032 #include <qpainter.h>
00033 #include <qpixmap.h>
00034 #include <qpointarray.h>
00035 #include <qrect.h>
00036 #include <qstring.h>
00037 
00038 #include <kdebug.h>
00039 #include <klocale.h>
00040 
00041 #include "kis_brush.h"
00042 #include "kis_debug_areas.h"
00043 #include "kis_gradient.h"
00044 #include "kis_image.h"
00045 #include "kis_iterators_pixel.h"
00046 #include "kis_layer.h"
00047 #include "kis_paint_device.h"
00048 #include "kis_pattern.h"
00049 #include "kis_rect.h"
00050 #include "kis_colorspace.h"
00051 #include "kis_types.h"
00052 #include "kis_vec.h"
00053 #include "kis_selection.h"
00054 #include "kis_gradient_painter.h"
00055 #include "kis_meta_registry.h"
00056 #include "kis_colorspace_factory_registry.h"
00057 
00058 namespace {
00059 
00060     class GradientShapeStrategy {
00061     public:
00062         GradientShapeStrategy(const KisPoint& gradientVectorStart, const KisPoint& gradientVectorEnd);
00063         virtual ~GradientShapeStrategy() {}
00064 
00065         virtual double valueAt(double x, double y) const = 0;
00066 
00067     protected:
00068         KisPoint m_gradientVectorStart;
00069         KisPoint m_gradientVectorEnd;
00070     };
00071 
00072     GradientShapeStrategy::GradientShapeStrategy(const KisPoint& gradientVectorStart, const KisPoint& gradientVectorEnd)
00073         : m_gradientVectorStart(gradientVectorStart), m_gradientVectorEnd(gradientVectorEnd)
00074     {
00075     }
00076 
00077 
00078     class LinearGradientStrategy : public GradientShapeStrategy {
00079         typedef GradientShapeStrategy super;
00080     public:
00081         LinearGradientStrategy(const KisPoint& gradientVectorStart, const KisPoint& gradientVectorEnd);
00082 
00083         virtual double valueAt(double x, double y) const;
00084 
00085     protected:
00086         double m_normalisedVectorX;
00087         double m_normalisedVectorY;
00088         double m_vectorLength;
00089     };
00090 
00091     LinearGradientStrategy::LinearGradientStrategy(const KisPoint& gradientVectorStart, const KisPoint& gradientVectorEnd)
00092         : super(gradientVectorStart, gradientVectorEnd)
00093     {
00094         double dx = gradientVectorEnd.x() - gradientVectorStart.x();
00095         double dy = gradientVectorEnd.y() - gradientVectorStart.y();
00096 
00097         m_vectorLength = sqrt((dx * dx) + (dy * dy));
00098 
00099         if (m_vectorLength < DBL_EPSILON) {
00100             m_normalisedVectorX = 0;
00101             m_normalisedVectorY = 0;
00102         }
00103         else {
00104             m_normalisedVectorX = dx / m_vectorLength;
00105             m_normalisedVectorY = dy / m_vectorLength;
00106         }
00107     }
00108 
00109     double LinearGradientStrategy::valueAt(double x, double y) const
00110     {
00111         double vx = x - m_gradientVectorStart.x();
00112         double vy = y - m_gradientVectorStart.y();
00113 
00114         // Project the vector onto the normalised gradient vector.
00115         double t = vx * m_normalisedVectorX + vy * m_normalisedVectorY;
00116 
00117         if (m_vectorLength < DBL_EPSILON) {
00118             t = 0;
00119         }
00120         else {
00121             // Scale to 0 to 1 over the gradient vector length.
00122             t /= m_vectorLength;
00123         }
00124 
00125         return t;
00126     }
00127 
00128 
00129     class BiLinearGradientStrategy : public LinearGradientStrategy {
00130         typedef LinearGradientStrategy super;
00131     public:
00132         BiLinearGradientStrategy(const KisPoint& gradientVectorStart, const KisPoint& gradientVectorEnd);
00133 
00134         virtual double valueAt(double x, double y) const;
00135     };
00136 
00137     BiLinearGradientStrategy::BiLinearGradientStrategy(const KisPoint& gradientVectorStart, const KisPoint& gradientVectorEnd)
00138         : super(gradientVectorStart, gradientVectorEnd)
00139     {
00140     }
00141 
00142     double BiLinearGradientStrategy::valueAt(double x, double y) const
00143     {
00144         double t = super::valueAt(x, y);
00145 
00146         // Reflect
00147         if (t < -DBL_EPSILON) {
00148             t = -t;
00149         }
00150 
00151         return t;
00152     }
00153 
00154 
00155     class RadialGradientStrategy : public GradientShapeStrategy {
00156         typedef GradientShapeStrategy super;
00157     public:
00158         RadialGradientStrategy(const KisPoint& gradientVectorStart, const KisPoint& gradientVectorEnd);
00159 
00160         virtual double valueAt(double x, double y) const;
00161 
00162     protected:
00163         double m_radius;
00164     };
00165 
00166     RadialGradientStrategy::RadialGradientStrategy(const KisPoint& gradientVectorStart, const KisPoint& gradientVectorEnd)
00167         : super(gradientVectorStart, gradientVectorEnd)
00168     {
00169         double dx = gradientVectorEnd.x() - gradientVectorStart.x();
00170         double dy = gradientVectorEnd.y() - gradientVectorStart.y();
00171 
00172         m_radius = sqrt((dx * dx) + (dy * dy));
00173     }
00174 
00175     double RadialGradientStrategy::valueAt(double x, double y) const
00176     {
00177         double dx = x - m_gradientVectorStart.x();
00178         double dy = y - m_gradientVectorStart.y();
00179 
00180         double distance = sqrt((dx * dx) + (dy * dy));
00181 
00182         double t;
00183 
00184         if (m_radius < DBL_EPSILON) {
00185             t = 0;
00186         }
00187         else {
00188             t = distance / m_radius;
00189         }
00190 
00191         return t;
00192     }
00193 
00194 
00195     class SquareGradientStrategy : public GradientShapeStrategy {
00196         typedef GradientShapeStrategy super;
00197     public:
00198         SquareGradientStrategy(const KisPoint& gradientVectorStart, const KisPoint& gradientVectorEnd);
00199 
00200         virtual double valueAt(double x, double y) const;
00201 
00202     protected:
00203         double m_normalisedVectorX;
00204         double m_normalisedVectorY;
00205         double m_vectorLength;
00206     };
00207 
00208     SquareGradientStrategy::SquareGradientStrategy(const KisPoint& gradientVectorStart, const KisPoint& gradientVectorEnd)
00209         : super(gradientVectorStart, gradientVectorEnd)
00210     {
00211         double dx = gradientVectorEnd.x() - gradientVectorStart.x();
00212         double dy = gradientVectorEnd.y() - gradientVectorStart.y();
00213 
00214         m_vectorLength = sqrt((dx * dx) + (dy * dy));
00215 
00216         if (m_vectorLength < DBL_EPSILON) {
00217             m_normalisedVectorX = 0;
00218             m_normalisedVectorY = 0;
00219         }
00220         else {
00221             m_normalisedVectorX = dx / m_vectorLength;
00222             m_normalisedVectorY = dy / m_vectorLength;
00223         }
00224     }
00225 
00226     double SquareGradientStrategy::valueAt(double x, double y) const
00227     {
00228         double px = x - m_gradientVectorStart.x();
00229         double py = y - m_gradientVectorStart.y();
00230 
00231         double distance1 = 0;
00232         double distance2 = 0;
00233 
00234         if (m_vectorLength > DBL_EPSILON) {
00235 
00236             // Point to line distance is:
00237             // distance = ((l0.y() - l1.y()) * p.x() + (l1.x() - l0.x()) * p.y() + l0.x() * l1.y() - l1.x() * l0.y()) / m_vectorLength;
00238             //
00239             // Here l0 = (0, 0) and |l1 - l0| = 1
00240 
00241             distance1 = -m_normalisedVectorY * px + m_normalisedVectorX * py;
00242             distance1 = fabs(distance1);
00243 
00244             // Rotate point by 90 degrees and get the distance to the perpendicular
00245             distance2 = -m_normalisedVectorY * -py + m_normalisedVectorX * px;
00246             distance2 = fabs(distance2);
00247         }
00248 
00249         double t = QMAX(distance1, distance2) / m_vectorLength;
00250 
00251         return t;
00252     }
00253 
00254 
00255     class ConicalGradientStrategy : public GradientShapeStrategy {
00256         typedef GradientShapeStrategy super;
00257     public:
00258         ConicalGradientStrategy(const KisPoint& gradientVectorStart, const KisPoint& gradientVectorEnd);
00259 
00260         virtual double valueAt(double x, double y) const;
00261 
00262     protected:
00263         double m_vectorAngle;
00264     };
00265 
00266     ConicalGradientStrategy::ConicalGradientStrategy(const KisPoint& gradientVectorStart, const KisPoint& gradientVectorEnd)
00267         : super(gradientVectorStart, gradientVectorEnd)
00268     {
00269         double dx = gradientVectorEnd.x() - gradientVectorStart.x();
00270         double dy = gradientVectorEnd.y() - gradientVectorStart.y();
00271 
00272         // Get angle from 0 to 2 PI.
00273         m_vectorAngle = atan2(dy, dx) + M_PI;
00274     }
00275 
00276     double ConicalGradientStrategy::valueAt(double x, double y) const
00277     {
00278         double px = x - m_gradientVectorStart.x();
00279         double py = y - m_gradientVectorStart.y();
00280 
00281         double angle = atan2(py, px) + M_PI;
00282 
00283         angle -= m_vectorAngle;
00284 
00285         if (angle < 0) {
00286             angle += 2 * M_PI;
00287         }
00288 
00289         double t = angle / (2 * M_PI);
00290 
00291         return t;
00292     }
00293 
00294 
00295     class ConicalSymetricGradientStrategy : public GradientShapeStrategy {
00296         typedef GradientShapeStrategy super;
00297     public:
00298         ConicalSymetricGradientStrategy(const KisPoint& gradientVectorStart, const KisPoint& gradientVectorEnd);
00299 
00300         virtual double valueAt(double x, double y) const;
00301 
00302     protected:
00303         double m_vectorAngle;
00304     };
00305 
00306     ConicalSymetricGradientStrategy::ConicalSymetricGradientStrategy(const KisPoint& gradientVectorStart, const KisPoint& gradientVectorEnd)
00307         : super(gradientVectorStart, gradientVectorEnd)
00308     {
00309         double dx = gradientVectorEnd.x() - gradientVectorStart.x();
00310         double dy = gradientVectorEnd.y() - gradientVectorStart.y();
00311 
00312         // Get angle from 0 to 2 PI.
00313         m_vectorAngle = atan2(dy, dx) + M_PI;
00314     }
00315 
00316     double ConicalSymetricGradientStrategy::valueAt(double x, double y) const
00317     {
00318         double px = x - m_gradientVectorStart.x();
00319         double py = y - m_gradientVectorStart.y();
00320 
00321         double angle = atan2(py, px) + M_PI;
00322 
00323         angle -= m_vectorAngle;
00324 
00325         if (angle < 0) {
00326             angle += 2 * M_PI;
00327         }
00328 
00329         double t;
00330 
00331         if (angle < M_PI) {
00332             t = angle / M_PI;
00333         }
00334         else {
00335             t = 1 - ((angle - M_PI) / M_PI);
00336         }
00337 
00338         return t;
00339     }
00340 
00341 
00342     class GradientRepeatStrategy {
00343     public:
00344         GradientRepeatStrategy() {}
00345         virtual ~GradientRepeatStrategy() {}
00346 
00347         virtual double valueAt(double t) const = 0;
00348     };
00349 
00350 
00351     class GradientRepeatNoneStrategy : public GradientRepeatStrategy {
00352     public:
00353         static GradientRepeatNoneStrategy *instance();
00354 
00355         virtual double valueAt(double t) const;
00356 
00357     private:
00358         GradientRepeatNoneStrategy() {}
00359 
00360         static GradientRepeatNoneStrategy *m_instance;
00361     };
00362 
00363     GradientRepeatNoneStrategy *GradientRepeatNoneStrategy::m_instance = 0;
00364 
00365     GradientRepeatNoneStrategy *GradientRepeatNoneStrategy::instance()
00366     {
00367         if (m_instance == 0) {
00368             m_instance = new GradientRepeatNoneStrategy();
00369             Q_CHECK_PTR(m_instance);
00370         }
00371 
00372         return m_instance;
00373     }
00374 
00375     // Output is clamped to 0 to 1.
00376     double GradientRepeatNoneStrategy::valueAt(double t) const
00377     {
00378         double value = t;
00379 
00380         if (t < DBL_EPSILON) {
00381             value = 0;
00382         }
00383         else
00384             if (t > 1 - DBL_EPSILON) {
00385                 value = 1;
00386             }
00387 
00388         return value;
00389     }
00390 
00391 
00392     class GradientRepeatForwardsStrategy : public GradientRepeatStrategy {
00393     public:
00394         static GradientRepeatForwardsStrategy *instance();
00395 
00396         virtual double valueAt(double t) const;
00397 
00398     private:
00399         GradientRepeatForwardsStrategy() {}
00400 
00401         static GradientRepeatForwardsStrategy *m_instance;
00402     };
00403 
00404     GradientRepeatForwardsStrategy *GradientRepeatForwardsStrategy::m_instance = 0;
00405 
00406     GradientRepeatForwardsStrategy *GradientRepeatForwardsStrategy::instance()
00407     {
00408         if (m_instance == 0) {
00409             m_instance = new GradientRepeatForwardsStrategy();
00410             Q_CHECK_PTR(m_instance);
00411         }
00412 
00413         return m_instance;
00414     }
00415 
00416     // Output is 0 to 1, 0 to 1, 0 to 1...
00417     double GradientRepeatForwardsStrategy::valueAt(double t) const
00418     {
00419         int i = static_cast<int>(t);
00420 
00421         if (t < DBL_EPSILON) {
00422             i--;
00423         }
00424 
00425         double value = t - i;
00426 
00427         return value;
00428     }
00429 
00430 
00431     class GradientRepeatAlternateStrategy : public GradientRepeatStrategy {
00432     public:
00433         static GradientRepeatAlternateStrategy *instance();
00434 
00435         virtual double valueAt(double t) const;
00436 
00437     private:
00438         GradientRepeatAlternateStrategy() {}
00439 
00440         static GradientRepeatAlternateStrategy *m_instance;
00441     };
00442 
00443     GradientRepeatAlternateStrategy *GradientRepeatAlternateStrategy::m_instance = 0;
00444 
00445     GradientRepeatAlternateStrategy *GradientRepeatAlternateStrategy::instance()
00446     {
00447         if (m_instance == 0) {
00448             m_instance = new GradientRepeatAlternateStrategy();
00449             Q_CHECK_PTR(m_instance);
00450         }
00451 
00452         return m_instance;
00453     }
00454 
00455     // Output is 0 to 1, 1 to 0, 0 to 1, 1 to 0...
00456     double GradientRepeatAlternateStrategy::valueAt(double t) const
00457     {
00458         if (t < 0) {
00459             t = -t;
00460         }
00461 
00462         int i = static_cast<int>(t);
00463 
00464                 double value = t - i;
00465 
00466         if (i % 2 == 1) {
00467             value = 1 - value;
00468         }
00469 
00470         return value;
00471     }
00472 }
00473 
00474 KisGradientPainter::KisGradientPainter()
00475     : super()
00476 {
00477     m_gradient = 0;
00478 }
00479 
00480 KisGradientPainter::KisGradientPainter(KisPaintDeviceSP device) : super(device), m_gradient(0)
00481 {
00482 }
00483 
00484 bool KisGradientPainter::paintGradient(const KisPoint& gradientVectorStart,
00485                        const KisPoint& gradientVectorEnd,
00486                        enumGradientShape shape,
00487                        enumGradientRepeat repeat,
00488                        double antiAliasThreshold,
00489                        bool reverseGradient,
00490                        Q_INT32 startx,
00491                        Q_INT32 starty,
00492                        Q_INT32 width,
00493                        Q_INT32 height)
00494 {
00495     m_cancelRequested = false;
00496 
00497     if (!m_gradient) return false;
00498 
00499     GradientShapeStrategy *shapeStrategy = 0;
00500 
00501     switch (shape) {
00502     case GradientShapeLinear:
00503         shapeStrategy = new LinearGradientStrategy(gradientVectorStart, gradientVectorEnd);
00504         break;
00505     case GradientShapeBiLinear:
00506         shapeStrategy = new BiLinearGradientStrategy(gradientVectorStart, gradientVectorEnd);
00507         break;
00508     case GradientShapeRadial:
00509         shapeStrategy = new RadialGradientStrategy(gradientVectorStart, gradientVectorEnd);
00510         break;
00511     case GradientShapeSquare:
00512         shapeStrategy = new SquareGradientStrategy(gradientVectorStart, gradientVectorEnd);
00513         break;
00514     case GradientShapeConical:
00515         shapeStrategy = new ConicalGradientStrategy(gradientVectorStart, gradientVectorEnd);
00516         break;
00517     case GradientShapeConicalSymetric:
00518         shapeStrategy = new ConicalSymetricGradientStrategy(gradientVectorStart, gradientVectorEnd);
00519         break;
00520     }
00521     Q_CHECK_PTR(shapeStrategy);
00522 
00523     GradientRepeatStrategy *repeatStrategy = 0;
00524 
00525     switch (repeat) {
00526     case GradientRepeatNone:
00527         repeatStrategy = GradientRepeatNoneStrategy::instance();
00528         break;
00529     case GradientRepeatForwards:
00530         repeatStrategy = GradientRepeatForwardsStrategy::instance();
00531         break;
00532     case GradientRepeatAlternate:
00533         repeatStrategy = GradientRepeatAlternateStrategy::instance();
00534         break;
00535     }
00536     Q_ASSERT(repeatStrategy != 0);
00537 
00538 
00539     //If the device has a selection only iterate over that selection
00540     QRect r;
00541     if( m_device->hasSelection() ) {
00542         r = m_device->selection()->selectedExactRect();
00543         startx = r.x();
00544         starty = r.y();
00545         width = r.width();
00546         height = r.height();
00547     }
00548 
00549     Q_INT32 endx = startx + width - 1;
00550     Q_INT32 endy = starty + height - 1;
00551 
00552     QImage layer (width, height, 32);
00553     layer.setAlphaBuffer(true);
00554 
00555     int pixelsProcessed = 0;
00556     int lastProgressPercent = 0;
00557 
00558     emit notifyProgressStage(i18n("Rendering gradient..."), 0);
00559 
00560     int totalPixels = width * height;
00561 
00562     if (antiAliasThreshold < 1 - DBL_EPSILON) {
00563         totalPixels *= 2;
00564     }
00565 
00566     for (int y = starty; y <= endy; y++) {
00567         for (int x = startx; x <= endx; x++) {
00568 
00569             double t = shapeStrategy->valueAt( x, y);
00570             t = repeatStrategy->valueAt(t);
00571 
00572             if (reverseGradient) {
00573                 t = 1 - t;
00574             }
00575 
00576             QColor color;
00577             Q_UINT8 opacity;
00578 
00579             m_gradient->colorAt(t, &color, &opacity);
00580 
00581             layer.setPixel(x - startx, y - starty,
00582                            qRgba(color.red(), color.green(), color.blue(), opacity));
00583 
00584             pixelsProcessed++;
00585 
00586             int progressPercent = (pixelsProcessed * 100) / totalPixels;
00587 
00588             if (progressPercent > lastProgressPercent) {
00589                 emit notifyProgress(progressPercent);
00590                 lastProgressPercent = progressPercent;
00591 
00592                 if (m_cancelRequested) {
00593                     break;
00594                 }
00595             }
00596             if (m_cancelRequested) {
00597                 break;
00598             }
00599         }
00600     }
00601 
00602     if (!m_cancelRequested && antiAliasThreshold < 1 - DBL_EPSILON) {
00603 
00604         QColor color;
00605         emit notifyProgressStage(i18n("Anti-aliasing gradient..."), lastProgressPercent);
00606         Q_UINT8 * layerPointer = layer.bits();
00607         for (int y = starty; y <= endy; y++) {
00608             for (int x = startx; x <= endx; x++) {
00609 
00610                 double maxDistance = 0;
00611 
00612                 Q_UINT8 redThis = layerPointer[2];
00613                 Q_UINT8 greenThis = layerPointer[1];
00614                 Q_UINT8 blueThis = layerPointer[0];
00615                 Q_UINT8 thisPixelOpacity = layerPointer[3];
00616 
00617                 for (int yOffset = -1; yOffset < 2; yOffset++) {
00618                     for (int xOffset = -1; xOffset < 2; xOffset++) {
00619 
00620                         if (xOffset != 0 || yOffset != 0) {
00621                             int sampleX = x + xOffset;
00622                             int sampleY = y + yOffset;
00623 
00624                             if (sampleX >= startx && sampleX <= endx && sampleY >= starty && sampleY <= endy) {
00625                                 uint x = sampleX - startx;
00626                                 uint y = sampleY - starty;
00627                                 Q_UINT8 * pixelPos = layer.bits() + (y * width * 4) + (x * 4);
00628                                 Q_UINT8 red = *(pixelPos +2);
00629                                 Q_UINT8 green = *(pixelPos + 1);
00630                                 Q_UINT8 blue = *pixelPos;
00631                                 Q_UINT8 opacity = *(pixelPos + 3);
00632 
00633                                 double dRed = (red * opacity - redThis * thisPixelOpacity) / 65535.0;
00634                                 double dGreen = (green * opacity - greenThis * thisPixelOpacity) / 65535.0;
00635                                 double dBlue = (blue * opacity - blueThis * thisPixelOpacity) / 65535.0;
00636 
00637                                 #define SQRT_3 1.7320508
00638 
00639                                 double distance =/* sqrt(*/dRed * dRed + dGreen * dGreen + dBlue * dBlue/*) / SQRT_3*/;
00640 
00641                                 if (distance > maxDistance) {
00642                                     maxDistance = distance;
00643                                 }
00644                             }
00645                         }
00646                     }
00647                 }
00648 
00649                 if (maxDistance > 3.*antiAliasThreshold*antiAliasThreshold) {
00650                     const int numSamples = 4;
00651 
00652                     int totalRed = 0;
00653                     int totalGreen = 0;
00654                     int totalBlue = 0;
00655                     int totalOpacity = 0;
00656 
00657                     for (int ySample = 0; ySample < numSamples; ySample++) {
00658                         for (int xSample = 0; xSample < numSamples; xSample++) {
00659 
00660                             double sampleWidth = 1.0 / numSamples;
00661 
00662                             double sampleX = x - 0.5 + (sampleWidth / 2) + xSample * sampleWidth;
00663                             double sampleY = y - 0.5 + (sampleWidth / 2) + ySample * sampleWidth;
00664 
00665                             double t = shapeStrategy->valueAt(sampleX, sampleY);
00666                             t = repeatStrategy->valueAt(t);
00667 
00668                             if (reverseGradient) {
00669                                 t = 1 - t;
00670                             }
00671 
00672                             Q_UINT8 opacity;
00673 
00674                             m_gradient->colorAt(t, &color, &opacity);
00675 
00676                             totalRed += color.red();
00677                             totalGreen += color.green();
00678                             totalBlue += color.blue();
00679                             totalOpacity += opacity;
00680                         }
00681                     }
00682 
00683                     int red = totalRed / (numSamples * numSamples);
00684                     int green = totalGreen / (numSamples * numSamples);
00685                     int blue = totalBlue / (numSamples * numSamples);
00686                     int opacity = totalOpacity / (numSamples * numSamples);
00687 
00688                     layer.setPixel(x - startx, y - starty, qRgba(red, green, blue, opacity));
00689                 }
00690 
00691                 pixelsProcessed++;
00692 
00693                 int progressPercent = (pixelsProcessed * 100) / totalPixels;
00694 
00695                 if (progressPercent > lastProgressPercent) {
00696                     emit notifyProgress(progressPercent);
00697                     lastProgressPercent = progressPercent;
00698 
00699                     if (m_cancelRequested) {
00700                         break;
00701                     }
00702                 }
00703                 layerPointer += 4;
00704             }
00705 
00706             if (m_cancelRequested) {
00707                 break;
00708             }
00709         }
00710     }
00711 
00712     if (!m_cancelRequested) {
00713         kdDebug() << "Have we got a selection? " << m_device->hasSelection() << endl;
00714         KisPaintDeviceSP dev = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getRGB8(), "temporary device for gradient");
00715         dev->writeBytes(layer.bits(), startx, starty, width, height);
00716         bltSelection(startx, starty, m_compositeOp, dev, m_opacity, startx, starty, width, height);
00717     }
00718     delete shapeStrategy;
00719 
00720     emit notifyProgressDone();
00721 
00722     return !m_cancelRequested;
00723 }
KDE Home | KDE Accessibility Home | Description of Access Keys