kdecore Library: kiconeffect.cpp Source File (kdecore Library)

| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# kiconeffect.cpp

    00001 /* vi: ts=8 sts=4 sw=4
    00002  * $Id: kiconeffect.cpp 389958 2005-02-16 15:51:35Z gunnar $
    00003  *
    00004  * This file is part of the KDE project, module kdecore.
    00005  * Copyright (C) 2000 Geert Jansen <jansen@kde.org>
    00006  * with minor additions and based on ideas from
    00007  * Torsten Rahn <torsten@kde.org>
    00008  *
    00009  * This is free software; it comes under the GNU Library General
    00010  * Public License, version 2. See the file "COPYING.LIB" for the
    00011  * exact licensing terms.
    00012  */
    00013
    00014 #include <config.h>
    00015 #include <unistd.h>
    00016 #include <math.h>
    00017
    00018 #include <qstring.h>
    00019 #include <qstringlist.h>
    00020 #include <qbitmap.h>
    00021 #include <qpixmap.h>
    00022 #include <qimage.h>
    00023 #include <qcolor.h>
    00024 #include <qwidget.h>
    00025 #include <qpainter.h>
    00026 #include <qpen.h>
    00027
    00028 #include <kdebug.h>
    00029 #include <kglobal.h>
    00030 #include <kconfig.h>
    00031 #include <kglobalsettings.h>
    00032 #include <kicontheme.h>
    00033 #include "kiconeffect.h"
    00034
    00035 #if defined(Q_WS_WIN) || defined(Q_WS_MACX)
    00036 static bool qt_use_xrender=true;
    00037 static bool qt_has_xft=true;
    00038 #else
    00039 extern bool qt_use_xrender;
    00040 extern bool qt_has_xft;
    00041 #endif
    00042 class KIconEffectPrivate
    00043 {
    00044 public:
    00045     QString mKey[6][3];
    00046     QColor  mColor2[6][3];
    00047 };
    00048
    00049 KIconEffect::KIconEffect()
    00050 {
    00051     d = new KIconEffectPrivate;
    00052     init();
    00053 }
    00054
    00055 KIconEffect::~KIconEffect()
    00056 {
    00057     delete d;
    00058     d = 0L;
    00059 }
    00060
    00061 void KIconEffect::init()
    00062 {
    00063     KConfig *config = KGlobal::config();
    00064
    00065     int i, j, effect=-1;
    00066     QStringList groups;
    00067     groups += "Desktop";
    00068     groups += "Toolbar";
    00069     groups += "MainToolbar";
    00070     groups += "Small";
    00071     groups += "Panel";
    00072
    00073     QStringList states;
    00074     states += "Default";
    00075     states += "Active";
    00076     states += "Disabled";
    00077
    00078     QStringList::ConstIterator it, it2;
    00079     QString _togray("togray");
    00080     QString _colorize("colorize");
    00081     QString _desaturate("desaturate");
    00082     QString _togamma("togamma");
    00083     QString _none("none");
    00084     QString _tomonochrome("tomonochrome");
    00085
    00086     KConfigGroupSaver cs(config, "default");
    00087
    00088     for (it=groups.begin(), i=0; it!=groups.end(); it++, i++)
    00089     {
    00090     // Default effects
    00091     mEffect[i][0] = NoEffect;
    00092     mEffect[i][1] =  ((i==0)||(i==4)) ? ToGamma : NoEffect;
    00093     mEffect[i][2] = ToGray;
    00094
    00095     mTrans[i][0] = false;
    00096     mTrans[i][1] = false;
    00097     mTrans[i][2] = true;
    00098         mValue[i][0] = 1.0;
    00099         mValue[i][1] = ((i==0)||(i==4)) ? 0.7 : 1.0;
    00100         mValue[i][2] = 1.0;
    00101         mColor[i][0] = QColor(144,128,248);
    00102         mColor[i][1] = QColor(169,156,255);
    00103         mColor[i][2] = QColor(34,202,0);
    00104         d->mColor2[i][0] = QColor(0,0,0);
    00105         d->mColor2[i][1] = QColor(0,0,0);
    00106         d->mColor2[i][2] = QColor(0,0,0);
    00107
    00108     config->setGroup(*it + "Icons");
    00109     for (it2=states.begin(), j=0; it2!=states.end(); it2++, j++)
    00110     {
    00111         QString tmp = config->readEntry(*it2 + "Effect");
    00112         if (tmp == _togray)
    00113         effect = ToGray;
    00114         else if (tmp == _colorize)
    00115         effect = Colorize;
    00116         else if (tmp == _desaturate)
    00117         effect = DeSaturate;
    00118         else if (tmp == _togamma)
    00119         effect = ToGamma;
    00120         else if (tmp == _tomonochrome)
    00121         effect = ToMonochrome;
    00122             else if (tmp == _none)
    00123         effect = NoEffect;
    00124         else
    00125         continue;
    00126         if(effect != -1)
    00127                 mEffect[i][j] = effect;
    00128         mValue[i][j] = config->readDoubleNumEntry(*it2 + "Value");
    00129         mColor[i][j] = config->readColorEntry(*it2 + "Color");
    00130         d->mColor2[i][j] = config->readColorEntry(*it2 + "Color2");
    00131         mTrans[i][j] = config->readBoolEntry(*it2 + "SemiTransparent");
    00132
    00133     }
    00134     }
    00135 }
    00136
    00137 bool KIconEffect::hasEffect(int group, int state) const
    00138 {
    00139     return mEffect[group][state] != NoEffect;
    00140 }
    00141
    00142 QString KIconEffect::fingerprint(int group, int state) const
    00143 {
    00144     if ( group >= KIcon::LastGroup ) return "";
    00145     QString cached = d->mKey[group][state];
    00146     if (cached.isEmpty())
    00147     {
    00148         QString tmp;
    00149         cached = tmp.setNum(mEffect[group][state]);
    00150         cached += ':';
    00151         cached += tmp.setNum(mValue[group][state]);
    00152         cached += ':';
    00153         cached += mTrans[group][state] ? QString::fromLatin1("trans")
    00154             : QString::fromLatin1("notrans");
    00155         if (mEffect[group][state] == Colorize || mEffect[group][state] == ToMonochrome)
    00156         {
    00157             cached += ':';
    00158             cached += mColor[group][state].name();
    00159         }
    00160         if (mEffect[group][state] == ToMonochrome)
    00161         {
    00162             cached += ':';
    00163             cached += d->mColor2[group][state].name();
    00164         }
    00165
    00166         d->mKey[group][state] = cached;
    00167     }
    00168
    00169     return cached;
    00170 }
    00171
    00172 QImage KIconEffect::apply(QImage image, int group, int state) const
    00173 {
    00174     if (state >= KIcon::LastState)
    00175     {
    00176     kdDebug(265) << "Illegal icon state: " << state << "\n";
    00177     return image;
    00178     }
    00179     if (group >= KIcon::LastGroup)
    00180     {
    00181     kdDebug(265) << "Illegal icon group: " << group << "\n";
    00182     return image;
    00183     }
    00184     return apply(image, mEffect[group][state], mValue[group][state],
    00185         mColor[group][state], d->mColor2[group][state], mTrans[group][state]);
    00186 }
    00187
    00188 QImage KIconEffect::apply(QImage image, int effect, float value, const QColor col, bool trans) const
    00189 {
    00190     return apply (image, effect, value, col, KGlobalSettings::baseColor(), trans);
    00191 }
    00192
    00193 QImage KIconEffect::apply(QImage image, int effect, float value, const QColor col, const QColor col2, bool trans) const
    00194 {
    00195     if (effect >= LastEffect )
    00196     {
    00197     kdDebug(265) << "Illegal icon effect: " << effect << "\n";
    00198     return image;
    00199     }
    00200     if (value > 1.0)
    00201     value = 1.0;
    00202     else if (value < 0.0)
    00203     value = 0.0;
    00204     switch (effect)
    00205     {
    00206     case ToGray:
    00207     toGray(image, value);
    00208     break;
    00209     case DeSaturate:
    00210     deSaturate(image, value);
    00211     break;
    00212     case Colorize:
    00213         colorize(image, col, value);
    00214         break;
    00215     case ToGamma:
    00216         toGamma(image, value);
    00217         break;
    00218     case ToMonochrome:
    00219         toMonochrome(image, col, col2, value);
    00220         break;
    00221     }
    00222     if (trans == true)
    00223     {
    00224     semiTransparent(image);
    00225     }
    00226     return image;
    00227 }
    00228
    00229 QPixmap KIconEffect::apply(QPixmap pixmap, int group, int state) const
    00230 {
    00231     if (state >= KIcon::LastState)
    00232     {
    00233     kdDebug(265) << "Illegal icon state: " << state << "\n";
    00234     return pixmap;
    00235     }
    00236     if (group >= KIcon::LastGroup)
    00237     {
    00238     kdDebug(265) << "Illegal icon group: " << group << "\n";
    00239     return pixmap;
    00240     }
    00241     return apply(pixmap, mEffect[group][state], mValue[group][state],
    00242         mColor[group][state], d->mColor2[group][state], mTrans[group][state]);
    00243 }
    00244
    00245 QPixmap KIconEffect::apply(QPixmap pixmap, int effect, float value,
    00246     const QColor col, bool trans) const
    00247 {
    00248     return apply (pixmap, effect, value, col, KGlobalSettings::baseColor(), trans);
    00249 }
    00250
    00251 QPixmap KIconEffect::apply(QPixmap pixmap, int effect, float value,
    00252     const QColor col, const QColor col2, bool trans) const
    00253 {
    00254     QPixmap result;
    00255
    00256     if (effect >= LastEffect )
    00257     {
    00258     kdDebug(265) << "Illegal icon effect: " << effect << "\n";
    00259     return result;
    00260     }
    00261
    00262     if ((trans == true) && (effect == NoEffect))
    00263     {
    00264         result = pixmap;
    00265         semiTransparent(result);
    00266     }
    00267     else if ( effect != NoEffect )
    00268     {
    00269         QImage tmpImg = pixmap.convertToImage();
    00270         tmpImg = apply(tmpImg, effect, value, col, col2, trans);
    00271         result.convertFromImage(tmpImg);
    00272     }
    00273     else
    00274         result = pixmap;
    00275
    00276     return result;
    00277 }
    00278
    00279 // Taken from KImageEffect. We don't want to link kdecore to kdeui! As long
    00280 // as this code is not too big, it doesn't seem much of a problem to me.
    00281
    00282 void KIconEffect::toGray(QImage &img, float value)
    00283 {
    00284     int pixels = (img.depth() > 8) ? img.width()*img.height()
    00285         : img.numColors();
    00286     unsigned int *data = img.depth() > 8 ? (unsigned int *) img.bits()
    00287         : (unsigned int *) img.colorTable();
    00288     int rval, gval, bval, val, alpha, i;
    00289     for (i=0; i<pixels; i++)
    00290     {
    00291     val = qGray(data[i]);
    00292     alpha = qAlpha(data[i]);
    00293     if (value < 1.0)
    00294     {
    00295         rval = static_cast<int>(value*val+(1.0-value)*qRed(data[i]));
    00296         gval = static_cast<int>(value*val+(1.0-value)*qGreen(data[i]));
    00297         bval = static_cast<int>(value*val+(1.0-value)*qBlue(data[i]));
    00298         data[i] = qRgba(rval, gval, bval, alpha);
    00299     } else
    00300         data[i] = qRgba(val, val, val, alpha);
    00301     }
    00302 }
    00303
    00304 void KIconEffect::colorize(QImage &img, const QColor &col, float value)
    00305 {
    00306     int pixels = (img.depth() > 8) ? img.width()*img.height()
    00307         : img.numColors();
    00308     unsigned int *data = img.depth() > 8 ? (unsigned int *) img.bits()
    00309         : (unsigned int *) img.colorTable();
    00310     int rval, gval, bval, val, alpha, i;
    00311     float rcol = col.red(), gcol = col.green(), bcol = col.blue();
    00312     for (i=0; i<pixels; i++)
    00313     {
    00314         val = qGray(data[i]);
    00315         if (val < 128)
    00316         {
    00317              rval = static_cast<int>(rcol/128*val);
    00318              gval = static_cast<int>(gcol/128*val);
    00319              bval = static_cast<int>(bcol/128*val);
    00320         }
    00321         else if (val > 128)
    00322         {
    00323              rval = static_cast<int>((val-128)*(2-rcol/128)+rcol-1);
    00324              gval = static_cast<int>((val-128)*(2-gcol/128)+gcol-1);
    00325              bval = static_cast<int>((val-128)*(2-bcol/128)+bcol-1);
    00326         }
    00327     else // val == 128
    00328     {
    00329              rval = static_cast<int>(rcol);
    00330              gval = static_cast<int>(gcol);
    00331              bval = static_cast<int>(bcol);
    00332     }
    00333     if (value < 1.0)
    00334     {
    00335         rval = static_cast<int>(value*rval+(1.0 - value)*qRed(data[i]));
    00336         gval = static_cast<int>(value*gval+(1.0 - value)*qGreen(data[i]));
    00337         bval = static_cast<int>(value*bval+(1.0 - value)*qBlue(data[i]));
    00338     }
    00339
    00340     alpha = qAlpha(data[i]);
    00341     data[i] = qRgba(rval, gval, bval, alpha);
    00342     }
    00343 }
    00344
    00345 void KIconEffect::toMonochrome(QImage &img, const QColor &black, const QColor &white, float value) {
    00346    int pixels = (img.depth() > 8) ? img.width()*img.height() : img.numColors();
    00347    unsigned int *data = img.depth() > 8 ? (unsigned int *) img.bits()
    00348          : (unsigned int *) img.colorTable();
    00349    int rval, gval, bval, alpha, i;
    00350    int rw = white.red(), gw = white.green(), bw = white.blue();
    00351    int rb = black.red(), gb = black.green(), bb = black.blue();
    00352
    00353    double values = 0, sum = 0;
    00354    bool grayscale = true;
    00355    // Step 1: determine the average brightness
    00356    for (i=0; i<pixels; i++) {
    00357        sum += qGray(data[i])*qAlpha(data[i]) + 255*(255-qAlpha(data[i]));
    00358        values += 255;
    00359        if ((qRed(data[i]) != qGreen(data[i]) ) || (qGreen(data[i]) != qBlue(data[i]) ))
    00360            grayscale = false;
    00361    }
    00362    double medium = sum/values;
    00363
    00364    // Step 2: Modify the image
    00365    if (grayscale) {
    00366        for (i=0; i<pixels; i++) {
    00367            int v = qRed(data[i]);
    00368            rval = static_cast<int>( ((255-v)*rb + v*rw)*value/255 + (1.0-value)*qRed(data[i]));
    00369            gval = static_cast<int>( ((255-v)*gb + v*gw)*value/255 + (1.0-value)*qGreen(data[i]));
    00370            bval = static_cast<int>( ((255-v)*bb + v*bw)*value/255 + (1.0-value)*qBlue(data[i]));
    00371
    00372            alpha = qAlpha(data[i]);
    00373            data[i] = qRgba(rval, gval, bval, alpha);
    00374        }
    00375    }
    00376    else {
    00377       for (i=0; i<pixels; i++) {
    00378          if (qGray(data[i]) <= medium) {
    00379             rval = static_cast<int>(value*rb+(1.0-value)*qRed(data[i]));
    00380             gval = static_cast<int>(value*gb+(1.0-value)*qGreen(data[i]));
    00381             bval = static_cast<int>(value*bb+(1.0-value)*qBlue(data[i]));
    00382          }
    00383          else {
    00384             rval = static_cast<int>(value*rw+(1.0-value)*qRed(data[i]));
    00385             gval = static_cast<int>(value*gw+(1.0-value)*qGreen(data[i]));
    00386             bval = static_cast<int>(value*bw+(1.0-value)*qBlue(data[i]));
    00387          }
    00388
    00389          alpha = qAlpha(data[i]);
    00390          data[i] = qRgba(rval, gval, bval, alpha);
    00391       }
    00392    }
    00393 }
    00394
    00395 void KIconEffect::deSaturate(QImage &img, float value)
    00396 {
    00397     int pixels = (img.depth() > 8) ? img.width()*img.height()
    00398         : img.numColors();
    00399     unsigned int *data = (img.depth() > 8) ? (unsigned int *) img.bits()
    00400         : (unsigned int *) img.colorTable();
    00401     QColor color;
    00402     int h, s, v, i;
    00403     for (i=0; i<pixels; i++)
    00404     {
    00405         color.setRgb(data[i]);
    00406         color.hsv(&h, &s, &v);
    00407         color.setHsv(h, (int) (s * (1.0 - value) + 0.5), v);
    00408     data[i] = qRgba(color.red(), color.green(), color.blue(),
    00409         qAlpha(data[i]));
    00410     }
    00411 }
    00412
    00413 void KIconEffect::toGamma(QImage &img, float value)
    00414 {
    00415     int pixels = (img.depth() > 8) ? img.width()*img.height()
    00416         : img.numColors();
    00417     unsigned int *data = (img.depth() > 8) ? (unsigned int *) img.bits()
    00418         : (unsigned int *) img.colorTable();
    00419     QColor color;
    00420     int i, rval, gval, bval;
    00421     float gamma;
    00422     gamma = 1/(2*value+0.5);
    00423
    00424     for (i=0; i<pixels; i++)
    00425     {
    00426         color.setRgb(data[i]);
    00427         color.rgb(&rval, &gval, &bval);
    00428         rval = static_cast<int>(pow(static_cast<float>(rval)/255 , gamma)*255);
    00429         gval = static_cast<int>(pow(static_cast<float>(gval)/255 , gamma)*255);
    00430         bval = static_cast<int>(pow(static_cast<float>(bval)/255 , gamma)*255);
    00431     data[i] = qRgba(rval, gval, bval, qAlpha(data[i]));
    00432     }
    00433 }
    00434
    00435 void KIconEffect::semiTransparent(QImage &img)
    00436 {
    00437     img.setAlphaBuffer(true);
    00438
    00439     int x, y;
    00440     if (img.depth() == 32)
    00441     {
    00442     int width  = img.width();
    00443     int height = img.height();
    00444
    00445     if (qt_use_xrender && qt_has_xft )
    00446       for (y=0; y<height; y++)
    00447       {
    00448 #ifdef WORDS_BIGENDIAN
    00449         uchar *line = (uchar*) img.scanLine(y);
    00450 #else
    00451         uchar *line = (uchar*) img.scanLine(y) + 3;
    00452 #endif
    00453         for (x=0; x<width; x++)
    00454         {
    00455         *line >>= 1;
    00456         line += 4;
    00457         }
    00458       }
    00459     else
    00460       for (y=0; y<height; y++)
    00461       {
    00462         QRgb *line = (QRgb *) img.scanLine(y);
    00463         for (x=(y%2); x<width; x+=2)
    00464         line[x] &= 0x00ffffff;
    00465       }
    00466
    00467     } else
    00468     {
    00469     // Insert transparent pixel into the clut.
    00470     int transColor = -1;
    00471
    00472         // search for a color that is already transparent
    00473         for (x=0; x<img.numColors(); x++)
    00474         {
    00475             // try to find already transparent pixel
    00476             if (qAlpha(img.color(x)) < 127)
    00477             {
    00478                 transColor = x;
    00479                 break;
    00480             }
    00481         }
    00482
    00483
    00484         // FIXME: image must have transparency
    00485         if(transColor < 0 || transColor >= img.numColors())
    00486             return;
    00487
    00488     img.setColor(transColor, 0);
    00489         if(img.depth() == 8)
    00490         {
    00491             for (y=0; y<img.height(); y++)
    00492             {
    00493                 unsigned char *line = img.scanLine(y);
    00494                 for (x=(y%2); x<img.width(); x+=2)
    00495                     line[x] = transColor;
    00496             }
    00497     }
    00498         else
    00499         {
    00500             // SLOOW, but simple, as we would have to
    00501             // deal with endianess etc on our own here
    00502             for (y=0; y<img.height(); y++)
    00503                 for (x=(y%2); x<img.width(); x+=2)
    00504                     img.setPixel(x, y, transColor);
    00505         }
    00506     }
    00507 }
    00508
    00509 void KIconEffect::semiTransparent(QPixmap &pix)
    00510 {
    00511     if ( qt_use_xrender && qt_has_xft )
    00512     {
    00513     QImage img=pix.convertToImage();
    00514     semiTransparent(img);
    00515     pix.convertFromImage(img);
    00516     return;
    00517     }
    00518
    00519     QImage img;
    00520     if (pix.mask() != 0L)
    00521     img = pix.mask()->convertToImage();
    00522     else
    00523     {
    00524     img.create(pix.size(), 1, 2, QImage::BigEndian);
    00525     img.fill(1);
    00526     }
    00527
    00528     for (int y=0; y<img.height(); y++)
    00529     {
    00530     QRgb *line = (QRgb *) img.scanLine(y);
    00531     QRgb pattern = (y % 2) ? 0x55555555 : 0xaaaaaaaa;
    00532     for (int x=0; x<(img.width()+31)/32; x++)
    00533         line[x] &= pattern;
    00534     }
    00535     QBitmap mask;
    00536     mask.convertFromImage(img);
    00537     pix.setMask(mask);
    00538 }
    00539
    00540 QImage KIconEffect::doublePixels(QImage src) const
    00541 {
    00542     QImage dst;
    00543     if (src.depth() == 1)
    00544     {
    00545     kdDebug(265) << "image depth 1 not supported\n";
    00546     return dst;
    00547     }
    00548
    00549     int w = src.width();
    00550     int h = src.height();
    00551     dst.create(w*2, h*2, src.depth());
    00552     dst.setAlphaBuffer(src.hasAlphaBuffer());
    00553
    00554     int x, y;
    00555     if (src.depth() == 32)
    00556     {
    00557     QRgb *l1, *l2;
    00558     for (y=0; y<h; y++)
    00559     {
    00560         l1 = (QRgb *) src.scanLine(y);
    00561         l2 = (QRgb *) dst.scanLine(y*2);
    00562         for (x=0; x<w; x++)
    00563         {
    00564         l2[x*2] = l2[x*2+1] = l1[x];
    00565         }
    00566         memcpy(dst.scanLine(y*2+1), l2, dst.bytesPerLine());
    00567     }
    00568     } else
    00569     {
    00570     for (x=0; x<src.numColors(); x++)
    00571         dst.setColor(x, src.color(x));
    00572
    00573     unsigned char *l1, *l2;
    00574     for (y=0; y<h; y++)
    00575     {
    00576         l1 = src.scanLine(y);
    00577         l2 = dst.scanLine(y*2);
    00578         for (x=0; x<w; x++)
    00579         {
    00580         l2[x*2] = l1[x];
    00581         l2[x*2+1] = l1[x];
    00582         }
    00583         memcpy(dst.scanLine(y*2+1), l2, dst.bytesPerLine());
    00584     }
    00585     }
    00586     return dst;
    00587 }
    00588
    00589 void KIconEffect::overlay(QImage &src, QImage &overlay)
    00590 {
    00591     if (src.depth() != overlay.depth())
    00592     {
    00593     kdDebug(265) << "Image depth src != overlay!\n";
    00594     return;
    00595     }
    00596     if (src.size() != overlay.size())
    00597     {
    00598     kdDebug(265) << "Image size src != overlay\n";
    00599     return;
    00600     }
    00601     if (!overlay.hasAlphaBuffer())
    00602     {
    00603     kdDebug(265) << "Overlay doesn't have alpha buffer!\n";
    00604     return;
    00605     }
    00606
    00607     int i, j;
    00608
    00609     // We don't do 1 bpp
    00610
    00611     if (src.depth() == 1)
    00612     {
    00613     kdDebug(265) << "1bpp not supported!\n";
    00614     return;
    00615     }
    00616
    00617     // Overlay at 8 bpp doesn't use alpha blending
    00618
    00619     if (src.depth() == 8)
    00620     {
    00621     if (src.numColors() + overlay.numColors() > 255)
    00622     {
    00623         kdDebug(265) << "Too many colors in src + overlay!\n";
    00624         return;
    00625     }
    00626
    00627     // Find transparent pixel in overlay
    00628     int trans;
    00629     for (trans=0; trans<overlay.numColors(); trans++)
    00630     {
    00631         if (qAlpha(overlay.color(trans)) == 0)
    00632         {
    00633         kdDebug(265) << "transparent pixel found at " << trans << "\n";
    00634         break;
    00635         }
    00636     }
    00637     if (trans == overlay.numColors())
    00638     {
    00639         kdDebug(265) << "transparent pixel not found!\n";
    00640         return;
    00641     }
    00642
    00643     // Merge color tables
    00644     int nc = src.numColors();
    00645     src.setNumColors(nc + overlay.numColors());
    00646     for (i=0; i<overlay.numColors(); i++)
    00647     {
    00648         src.setColor(nc+i, overlay.color(i));
    00649     }
    00650
    00651     // Overwrite nontransparent pixels.
    00652     unsigned char *oline, *sline;
    00653     for (i=0; i<src.height(); i++)
    00654     {
    00655         oline = overlay.scanLine(i);
    00656         sline = src.scanLine(i);
    00657         for (j=0; j<src.width(); j++)
    00658         {
    00659         if (oline[j] != trans)
    00660             sline[j] = oline[j]+nc;
    00661         }
    00662     }
    00663     }
    00664
    00665     // Overlay at 32 bpp does use alpha blending
    00666
    00667     if (src.depth() == 32)
    00668     {
    00669     QRgb *oline, *sline;
    00670     int r1, g1, b1, a1;
    00671     int r2, g2, b2, a2;
    00672
    00673     for (i=0; i<src.height(); i++)
    00674     {
    00675         oline = (QRgb *) overlay.scanLine(i);
    00676         sline = (QRgb *) src.scanLine(i);
    00677
    00678         for (j=0; j<src.width(); j++)
    00679         {
    00680         r1 = qRed(oline[j]);
    00681         g1 = qGreen(oline[j]);
    00682         b1 = qBlue(oline[j]);
    00683         a1 = qAlpha(oline[j]);
    00684
    00685         r2 = qRed(sline[j]);
    00686         g2 = qGreen(sline[j]);
    00687         b2 = qBlue(sline[j]);
    00688         a2 = qAlpha(sline[j]);
    00689
    00690         r2 = (a1 * r1 + (0xff - a1) * r2) >> 8;
    00691         g2 = (a1 * g1 + (0xff - a1) * g2) >> 8;
    00692         b2 = (a1 * b1 + (0xff - a1) * b2) >> 8;
    00693         a2 = QMAX(a1, a2);
    00694
    00695         sline[j] = qRgba(r2, g2, b2, a2);
    00696         }
    00697     }
    00698     }
    00699
    00700     return;
    00701 }
    00702
    00703     void
    00704 KIconEffect::visualActivate(QWidget * widget, QRect rect)
    00705 {
    00706     if (!KGlobalSettings::visualActivate())
    00707         return;
    00708
    00709     uint actSpeed = KGlobalSettings::visualActivateSpeed();
    00710
    00711     uint actCount = QMIN(rect.width(), rect.height()) / 2;
    00712
    00713     // Clip actCount to range 1..10.
    00714
    00715     if (actCount < 1)
    00716         actCount = 1;
    00717
    00718     else if (actCount > 10)
    00719         actCount = 10;
    00720
    00721     // Clip actSpeed to range 1..100.
    00722
    00723     if (actSpeed < 1)
    00724         actSpeed = 1;
    00725
    00726     else if (actSpeed > 100)
    00727         actSpeed = 100;
    00728
    00729     // actSpeed needs to be converted to actDelay.
    00730     // actDelay is inversely proportional to actSpeed and needs to be
    00731     // divided up into actCount portions.
    00732     // We also convert the us value to ms.
    00733
    00734     unsigned int actDelay = (1000 * (100 - actSpeed)) / actCount;
    00735
    00736     //kdDebug() << "actCount=" << actCount << " actDelay=" << actDelay << endl;
    00737
    00738     QPoint c = rect.center();
    00739
    00740     QPainter p(widget);
    00741
    00742     // Use NotROP to avoid having to repaint the pixmap each time.
    00743     p.setPen(QPen(Qt::black, 2, Qt::DotLine));
    00744     p.setRasterOp(Qt::NotROP);
    00745
    00746     // The spacing between the rects we draw.
    00747     // Use the minimum of width and height to avoid painting outside the
    00748     // pixmap area.
    00749     //unsigned int delta(QMIN(rect.width() / actCount, rect.height() / actCount));
    00750
    00751     // Support for rectangles by David
    00752     unsigned int deltaX = rect.width() / actCount;
    00753     unsigned int deltaY = rect.height() / actCount;
    00754
    00755     for (unsigned int i = 1; i < actCount; i++) {
    00756
    00757         int w = i * deltaX;
    00758         int h = i * deltaY;
    00759
    00760         rect.setRect(c.x() - w / 2, c.y() - h / 2, w, h);
    00761
    00762         p.drawRect(rect);
    00763         p.flush();
    00764
    00765         usleep(actDelay);
    00766
    00767         p.drawRect(rect);
    00768     }
    00769 }
    00770

This file is part of the documentation for kdecore Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:18:04 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003