• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

kiconeffect.cpp
00001 /* vi: ts=8 sts=4 sw=4
00002  * $Id$
00003  *
00004  * This file is part of the KDE project, module tdecore.
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 <tqstring.h>
00019 #include <tqstringlist.h>
00020 #include <tqbitmap.h>
00021 #include <tqpixmap.h>
00022 #include <tqimage.h>
00023 #include <tqcolor.h>
00024 #include <tqwidget.h>
00025 #include <tqpainter.h>
00026 #include <tqpen.h>
00027 #include <tqapplication.h>
00028 #include <tqpoint.h>
00029 #include <tqrect.h>
00030 
00031 #include <kdebug.h>
00032 #include <tdeglobal.h>
00033 #include <tdeconfig.h>
00034 #include <tdeglobalsettings.h>
00035 #include <kicontheme.h>
00036 #include "kiconeffect.h"
00037 
00038 #if defined(Q_WS_WIN) || defined(Q_WS_MACX)
00039 static bool tqt_use_xrender=true;
00040 static bool tqt_has_xft=true;
00041 #else
00042 extern bool tqt_use_xrender;
00043 extern bool tqt_has_xft;
00044 #endif
00045 class TDEIconEffectPrivate
00046 {
00047 public:
00048     TQString mKey[6][3];
00049     TQColor  mColor2[6][3];
00050 };
00051 
00052 TDEIconEffect::TDEIconEffect()
00053 {
00054     d = new TDEIconEffectPrivate;
00055     init();
00056 }
00057 
00058 TDEIconEffect::~TDEIconEffect()
00059 {
00060     delete d;
00061     d = 0L;
00062 }
00063 
00064 void TDEIconEffect::init()
00065 {
00066     TDEConfig *config = TDEGlobal::config();
00067 
00068     int i, j, effect=-1;
00069     TQStringList groups;
00070     groups += "Desktop";
00071     groups += "Toolbar";
00072     groups += "MainToolbar";
00073     groups += "Small";
00074     groups += "Panel";
00075 
00076     TQStringList states;
00077     states += "Default";
00078     states += "Active";
00079     states += "Disabled";
00080 
00081     TQStringList::ConstIterator it, it2;
00082     TQString _togray("togray");
00083     TQString _colorize("colorize");
00084     TQString _desaturate("desaturate");
00085     TQString _togamma("togamma");
00086     TQString _none("none");
00087     TQString _tomonochrome("tomonochrome");
00088 
00089     TDEConfigGroupSaver cs(config, "default");
00090 
00091     for (it=groups.begin(), i=0; it!=groups.end(); it++, i++)
00092     {
00093     // Default effects
00094     mEffect[i][0] = NoEffect;
00095     mEffect[i][1] =  ((i==0)||(i==4)) ? ToGamma : NoEffect;
00096     mEffect[i][2] = ToGray; 
00097     
00098     mTrans[i][0] = false;
00099     mTrans[i][1] = false;
00100     mTrans[i][2] = true;
00101         mValue[i][0] = 1.0;
00102         mValue[i][1] = ((i==0)||(i==4)) ? 0.7 : 1.0;
00103         mValue[i][2] = 1.0;
00104         mColor[i][0] = TQColor(144,128,248);
00105         mColor[i][1] = TQColor(169,156,255);
00106         mColor[i][2] = TQColor(34,202,0);
00107         d->mColor2[i][0] = TQColor(0,0,0);
00108         d->mColor2[i][1] = TQColor(0,0,0);
00109         d->mColor2[i][2] = TQColor(0,0,0);
00110 
00111     config->setGroup(*it + "Icons");
00112     for (it2=states.begin(), j=0; it2!=states.end(); it2++, j++)
00113     {
00114         TQString tmp = config->readEntry(*it2 + "Effect");
00115         if (tmp == _togray)
00116         effect = ToGray;
00117         else if (tmp == _colorize)
00118         effect = Colorize;
00119         else if (tmp == _desaturate)
00120         effect = DeSaturate;
00121         else if (tmp == _togamma)
00122         effect = ToGamma;
00123         else if (tmp == _tomonochrome)
00124         effect = ToMonochrome;
00125             else if (tmp == _none)
00126         effect = NoEffect;
00127         else
00128         continue;
00129         if(effect != -1)
00130                 mEffect[i][j] = effect;
00131         mValue[i][j] = config->readDoubleNumEntry(*it2 + "Value");
00132         mColor[i][j] = config->readColorEntry(*it2 + "Color");
00133         d->mColor2[i][j] = config->readColorEntry(*it2 + "Color2");
00134         mTrans[i][j] = config->readBoolEntry(*it2 + "SemiTransparent");
00135 
00136     }
00137     }    
00138 }
00139 
00140 bool TDEIconEffect::hasEffect(int group, int state) const
00141 {
00142     return mEffect[group][state] != NoEffect;
00143 }
00144 
00145 TQString TDEIconEffect::fingerprint(int group, int state) const
00146 {
00147     if ( group >= TDEIcon::LastGroup ) return "";
00148     TQString cached = d->mKey[group][state];
00149     if (cached.isEmpty())
00150     {
00151         TQString tmp;
00152         cached = tmp.setNum(mEffect[group][state]);
00153         cached += ':';
00154         cached += tmp.setNum(mValue[group][state]);
00155         cached += ':';
00156         cached += mTrans[group][state] ? TQString::fromLatin1("trans")
00157             : TQString::fromLatin1("notrans");
00158         if (mEffect[group][state] == Colorize || mEffect[group][state] == ToMonochrome)
00159         {
00160             cached += ':';
00161             cached += mColor[group][state].name();
00162         }
00163         if (mEffect[group][state] == ToMonochrome)
00164         {
00165             cached += ':';
00166             cached += d->mColor2[group][state].name();
00167         }
00168     
00169         d->mKey[group][state] = cached;    
00170     }
00171     
00172     return cached;
00173 }
00174 
00175 TQImage TDEIconEffect::apply(TQImage image, int group, int state) const
00176 {
00177     if (state >= TDEIcon::LastState)
00178     {
00179     kdDebug(265) << "Illegal icon state: " << state << "\n";
00180     return image;
00181     }
00182     if (group >= TDEIcon::LastGroup)
00183     {
00184     kdDebug(265) << "Illegal icon group: " << group << "\n";
00185     return image;
00186     }
00187     return apply(image, mEffect[group][state], mValue[group][state],
00188         mColor[group][state], d->mColor2[group][state], mTrans[group][state]);
00189 }
00190 
00191 TQImage TDEIconEffect::apply(TQImage image, int effect, float value, const TQColor col, bool trans) const
00192 {
00193     return apply (image, effect, value, col, TDEGlobalSettings::baseColor(), trans);
00194 }
00195 
00196 TQImage TDEIconEffect::apply(TQImage image, int effect, float value, const TQColor col, const TQColor col2, bool trans) const
00197 {
00198     if (effect >= LastEffect )
00199     {
00200     kdDebug(265) << "Illegal icon effect: " << effect << "\n";
00201     return image;
00202     }
00203     if (value > 1.0)
00204     value = 1.0;
00205     else if (value < 0.0)
00206     value = 0.0;
00207     switch (effect)
00208     {
00209     case ToGray:
00210     toGray(image, value);
00211     break;
00212     case DeSaturate:
00213     deSaturate(image, value);
00214     break;
00215     case Colorize:
00216         colorize(image, col, value);
00217         break;
00218     case ToGamma:
00219         toGamma(image, value);
00220         break;
00221     case ToMonochrome:
00222         toMonochrome(image, col, col2, value);
00223         break;
00224     }
00225     if (trans == true)
00226     {
00227     semiTransparent(image);
00228     }
00229     return image;
00230 }
00231 
00232 TQPixmap TDEIconEffect::apply(TQPixmap pixmap, int group, int state) const
00233 {
00234     if (state >= TDEIcon::LastState)
00235     {
00236     kdDebug(265) << "Illegal icon state: " << state << "\n";
00237     return pixmap;
00238     }
00239     if (group >= TDEIcon::LastGroup)
00240     {
00241     kdDebug(265) << "Illegal icon group: " << group << "\n";
00242     return pixmap;
00243     }
00244     return apply(pixmap, mEffect[group][state], mValue[group][state],
00245         mColor[group][state], d->mColor2[group][state], mTrans[group][state]);
00246 }
00247 
00248 TQPixmap TDEIconEffect::apply(TQPixmap pixmap, int effect, float value,
00249     const TQColor col, bool trans) const
00250 {
00251     return apply (pixmap, effect, value, col, TDEGlobalSettings::baseColor(), trans);
00252 }
00253 
00254 TQPixmap TDEIconEffect::apply(TQPixmap pixmap, int effect, float value,
00255     const TQColor col, const TQColor col2, bool trans) const
00256 {
00257     TQPixmap result;
00258 
00259     if (effect >= LastEffect )
00260     {
00261     kdDebug(265) << "Illegal icon effect: " << effect << "\n";
00262     return result;
00263     }
00264 
00265     if ((trans == true) && (effect == NoEffect))
00266     {
00267         result = pixmap;
00268         semiTransparent(result);
00269     }
00270     else if ( effect != NoEffect )
00271     {
00272         TQImage tmpImg = pixmap.convertToImage();
00273         tmpImg = apply(tmpImg, effect, value, col, col2, trans);
00274         result.convertFromImage(tmpImg);
00275     }
00276     else
00277         result = pixmap;
00278 
00279     return result;
00280 }
00281 
00282 // Taken from KImageEffect. We don't want to link tdecore to tdeui! As long
00283 // as this code is not too big, it doesn't seem much of a problem to me.
00284 
00285 void TDEIconEffect::toGray(TQImage &img, float value)
00286 {
00287     int pixels = (img.depth() > 8) ? img.width()*img.height()
00288         : img.numColors();
00289     unsigned int *data = img.depth() > 8 ? (unsigned int *) img.bits()
00290         : (unsigned int *) img.tqcolorTable();
00291     int rval, gval, bval, val, alpha, i;
00292     for (i=0; i<pixels; i++)
00293     {
00294     val = tqGray(data[i]);
00295     alpha = tqAlpha(data[i]);
00296     if (value < 1.0)
00297     {
00298         rval = static_cast<int>(value*val+(1.0-value)*tqRed(data[i]));
00299         gval = static_cast<int>(value*val+(1.0-value)*tqGreen(data[i]));
00300         bval = static_cast<int>(value*val+(1.0-value)*tqBlue(data[i]));
00301         data[i] = tqRgba(rval, gval, bval, alpha);
00302     } else
00303         data[i] = tqRgba(val, val, val, alpha);
00304     }
00305 }
00306 
00307 void TDEIconEffect::colorize(TQImage &img, const TQColor &col, float value)
00308 {
00309     int pixels = (img.depth() > 8) ? img.width()*img.height()
00310         : img.numColors();
00311     unsigned int *data = img.depth() > 8 ? (unsigned int *) img.bits()
00312         : (unsigned int *) img.tqcolorTable();
00313     int rval, gval, bval, val, alpha, i;
00314     float rcol = col.red(), gcol = col.green(), bcol = col.blue();
00315     for (i=0; i<pixels; i++)
00316     {
00317         val = tqGray(data[i]);
00318         if (val < 128)
00319         {
00320              rval = static_cast<int>(rcol/128*val);
00321              gval = static_cast<int>(gcol/128*val);
00322              bval = static_cast<int>(bcol/128*val);
00323         }
00324         else if (val > 128)
00325         {
00326              rval = static_cast<int>((val-128)*(2-rcol/128)+rcol-1);
00327              gval = static_cast<int>((val-128)*(2-gcol/128)+gcol-1);
00328              bval = static_cast<int>((val-128)*(2-bcol/128)+bcol-1);
00329         }
00330     else // val == 128
00331     {
00332              rval = static_cast<int>(rcol);
00333              gval = static_cast<int>(gcol);
00334              bval = static_cast<int>(bcol);
00335     }
00336     if (value < 1.0)
00337     {
00338         rval = static_cast<int>(value*rval+(1.0 - value)*tqRed(data[i]));
00339         gval = static_cast<int>(value*gval+(1.0 - value)*tqGreen(data[i]));
00340         bval = static_cast<int>(value*bval+(1.0 - value)*tqBlue(data[i]));
00341     }
00342 
00343     alpha = tqAlpha(data[i]);
00344     data[i] = tqRgba(rval, gval, bval, alpha);
00345     }
00346 }
00347 
00348 void TDEIconEffect::toMonochrome(TQImage &img, const TQColor &black, const TQColor &white, float value) {
00349    int pixels = (img.depth() > 8) ? img.width()*img.height() : img.numColors();
00350    unsigned int *data = img.depth() > 8 ? (unsigned int *) img.bits()
00351          : (unsigned int *) img.tqcolorTable();
00352    int rval, gval, bval, alpha, i;
00353    int rw = white.red(), gw = white.green(), bw = white.blue();
00354    int rb = black.red(), gb = black.green(), bb = black.blue();
00355    
00356    double values = 0, sum = 0;
00357    bool grayscale = true;
00358    // Step 1: determine the average brightness
00359    for (i=0; i<pixels; i++) {
00360        sum += tqGray(data[i])*tqAlpha(data[i]) + 255*(255-tqAlpha(data[i]));
00361        values += 255;
00362        if ((tqRed(data[i]) != tqGreen(data[i]) ) || (tqGreen(data[i]) != tqBlue(data[i]) ))
00363            grayscale = false;
00364    }
00365    double medium = sum/values;
00366 
00367    // Step 2: Modify the image
00368    if (grayscale) {
00369        for (i=0; i<pixels; i++) {
00370            int v = tqRed(data[i]);
00371            rval = static_cast<int>( ((255-v)*rb + v*rw)*value/255 + (1.0-value)*tqRed(data[i]));
00372            gval = static_cast<int>( ((255-v)*gb + v*gw)*value/255 + (1.0-value)*tqGreen(data[i]));
00373            bval = static_cast<int>( ((255-v)*bb + v*bw)*value/255 + (1.0-value)*tqBlue(data[i]));
00374 
00375            alpha = tqAlpha(data[i]);
00376            data[i] = tqRgba(rval, gval, bval, alpha);
00377        }
00378    }
00379    else {
00380       for (i=0; i<pixels; i++) {
00381          if (tqGray(data[i]) <= medium) {
00382             rval = static_cast<int>(value*rb+(1.0-value)*tqRed(data[i]));
00383             gval = static_cast<int>(value*gb+(1.0-value)*tqGreen(data[i]));
00384             bval = static_cast<int>(value*bb+(1.0-value)*tqBlue(data[i]));
00385          }
00386          else {
00387             rval = static_cast<int>(value*rw+(1.0-value)*tqRed(data[i]));
00388             gval = static_cast<int>(value*gw+(1.0-value)*tqGreen(data[i]));
00389             bval = static_cast<int>(value*bw+(1.0-value)*tqBlue(data[i]));
00390          }
00391 
00392          alpha = tqAlpha(data[i]);
00393          data[i] = tqRgba(rval, gval, bval, alpha);
00394       }
00395    }
00396 }
00397 
00398 void TDEIconEffect::deSaturate(TQImage &img, float value)
00399 {
00400     int pixels = (img.depth() > 8) ? img.width()*img.height()
00401         : img.numColors();
00402     unsigned int *data = (img.depth() > 8) ? (unsigned int *) img.bits()
00403         : (unsigned int *) img.tqcolorTable();
00404     TQColor color;
00405     int h, s, v, i;
00406     for (i=0; i<pixels; i++)
00407     {
00408         color.setRgb(data[i]);
00409         color.hsv(&h, &s, &v);
00410         color.setHsv(h, (int) (s * (1.0 - value) + 0.5), v);
00411     data[i] = tqRgba(color.red(), color.green(), color.blue(),
00412         tqAlpha(data[i]));
00413     }
00414 }
00415 
00416 void TDEIconEffect::toGamma(TQImage &img, float value)
00417 {
00418     int pixels = (img.depth() > 8) ? img.width()*img.height()
00419         : img.numColors();
00420     unsigned int *data = (img.depth() > 8) ? (unsigned int *) img.bits()
00421         : (unsigned int *) img.tqcolorTable();
00422     TQColor color;
00423     int i, rval, gval, bval;
00424     float gamma;
00425     gamma = 1/(2*value+0.5);
00426 
00427     for (i=0; i<pixels; i++)
00428     {
00429         color.setRgb(data[i]);
00430         color.rgb(&rval, &gval, &bval);
00431         rval = static_cast<int>(pow(static_cast<float>(rval)/255 , gamma)*255);
00432         gval = static_cast<int>(pow(static_cast<float>(gval)/255 , gamma)*255);
00433         bval = static_cast<int>(pow(static_cast<float>(bval)/255 , gamma)*255);
00434     data[i] = tqRgba(rval, gval, bval, tqAlpha(data[i]));
00435     }
00436 }
00437 
00438 void TDEIconEffect::semiTransparent(TQImage &img)
00439 {
00440     img.setAlphaBuffer(true);
00441 
00442     int x, y;
00443     if (img.depth() == 32)
00444     {
00445     int width  = img.width();
00446     int height = img.height();
00447     
00448     if (tqt_use_xrender && tqt_has_xft )
00449       for (y=0; y<height; y++)
00450       {
00451 #ifdef WORDS_BIGENDIAN
00452         uchar *line = (uchar*) img.scanLine(y);
00453 #else
00454         uchar *line = (uchar*) img.scanLine(y) + 3;
00455 #endif
00456         for (x=0; x<width; x++)
00457         {
00458         *line >>= 1;
00459         line += 4;
00460         }
00461       }
00462     else
00463       for (y=0; y<height; y++)
00464       {
00465         QRgb *line = (QRgb *) img.scanLine(y);
00466         for (x=(y%2); x<width; x+=2)
00467         line[x] &= 0x00ffffff;
00468       }
00469 
00470     } else
00471     {
00472     // Insert transparent pixel into the clut.
00473     int transColor = -1;
00474 
00475         // search for a color that is already transparent
00476         for (x=0; x<img.numColors(); x++)
00477         {
00478             // try to find already transparent pixel
00479             if (tqAlpha(img.color(x)) < 127)
00480             {
00481                 transColor = x;
00482                 break;
00483             }
00484         }
00485 
00486 
00487         // FIXME: image must have transparency
00488         if(transColor < 0 || transColor >= img.numColors())
00489             return;
00490 
00491     img.setColor(transColor, 0);
00492         if(img.depth() == 8)
00493         {
00494             for (y=0; y<img.height(); y++)
00495             {
00496                 unsigned char *line = img.scanLine(y);
00497                 for (x=(y%2); x<img.width(); x+=2)
00498                     line[x] = transColor;
00499             }
00500     }
00501         else
00502         {
00503             // SLOOW, but simple, as we would have to
00504             // deal with endianess etc on our own here
00505             for (y=0; y<img.height(); y++)
00506                 for (x=(y%2); x<img.width(); x+=2)
00507                     img.setPixel(x, y, transColor);
00508         }
00509     }
00510 }
00511 
00512 void TDEIconEffect::semiTransparent(TQPixmap &pix)
00513 {
00514     if ( tqt_use_xrender && tqt_has_xft )
00515     {
00516     TQImage img=pix.convertToImage();
00517     semiTransparent(img);
00518     pix.convertFromImage(img);
00519     return;
00520     }
00521 
00522     TQImage img;
00523     if (pix.mask() != 0L)
00524     img = pix.mask()->convertToImage();
00525     else
00526     {
00527     img.create(pix.size(), 1, 2, TQImage::BigEndian);
00528     img.fill(1);
00529     }
00530 
00531     for (int y=0; y<img.height(); y++)
00532     {
00533     QRgb *line = (QRgb *) img.scanLine(y);
00534     QRgb pattern = (y % 2) ? 0x55555555 : 0xaaaaaaaa;
00535     for (int x=0; x<(img.width()+31)/32; x++)
00536         line[x] &= pattern;
00537     }
00538     TQBitmap mask;
00539     mask.convertFromImage(img);
00540     pix.setMask(mask);
00541 }
00542 
00543 TQImage TDEIconEffect::doublePixels(TQImage src) const
00544 {
00545     TQImage dst;
00546     if (src.depth() == 1)
00547     {
00548     kdDebug(265) << "image depth 1 not supported\n";
00549     return dst;
00550     }
00551 
00552     int w = src.width();
00553     int h = src.height();
00554     dst.create(w*2, h*2, src.depth());
00555     dst.setAlphaBuffer(src.hasAlphaBuffer());
00556 
00557     int x, y;
00558     if (src.depth() == 32)
00559     {
00560     QRgb *l1, *l2;
00561     for (y=0; y<h; y++)
00562     {
00563         l1 = (QRgb *) src.scanLine(y);
00564         l2 = (QRgb *) dst.scanLine(y*2);
00565         for (x=0; x<w; x++)
00566         {
00567         l2[x*2] = l2[x*2+1] = l1[x];
00568         }
00569         memcpy(dst.scanLine(y*2+1), l2, dst.bytesPerLine());
00570     }
00571     } else
00572     {
00573     for (x=0; x<src.numColors(); x++)
00574         dst.setColor(x, src.color(x));
00575 
00576     unsigned char *l1, *l2;
00577     for (y=0; y<h; y++)
00578     {
00579         l1 = src.scanLine(y);
00580         l2 = dst.scanLine(y*2);
00581         for (x=0; x<w; x++)
00582         {
00583         l2[x*2] = l1[x];
00584         l2[x*2+1] = l1[x];
00585         }
00586         memcpy(dst.scanLine(y*2+1), l2, dst.bytesPerLine());
00587     }
00588     }
00589     return dst;
00590 }
00591 
00592 void TDEIconEffect::overlay(TQImage &src, TQImage &overlay)
00593 {
00594     if (src.depth() != overlay.depth())
00595     {
00596     kdDebug(265) << "Image depth src != overlay!\n";
00597     return;
00598     }
00599     if (src.size() != overlay.size())
00600     {
00601     kdDebug(265) << "Image size src != overlay\n";
00602     return;
00603     }
00604     if (!overlay.hasAlphaBuffer())
00605     {
00606     kdDebug(265) << "Overlay doesn't have alpha buffer!\n";
00607     return;
00608     }
00609 
00610     int i, j;
00611 
00612     // We don't do 1 bpp
00613 
00614     if (src.depth() == 1)
00615     {
00616     kdDebug(265) << "1bpp not supported!\n";
00617     return;
00618     }
00619 
00620     // Overlay at 8 bpp doesn't use alpha blending
00621 
00622     if (src.depth() == 8)
00623     {
00624     if (src.numColors() + overlay.numColors() > 255)
00625     {
00626         kdDebug(265) << "Too many colors in src + overlay!\n";
00627         return;
00628     }
00629 
00630     // Find transparent pixel in overlay
00631     int trans;
00632     for (trans=0; trans<overlay.numColors(); trans++)
00633     {
00634         if (tqAlpha(overlay.color(trans)) == 0)
00635         {
00636         kdDebug(265) << "transparent pixel found at " << trans << "\n";
00637         break;
00638         }
00639     }
00640     if (trans == overlay.numColors())
00641     {
00642         kdDebug(265) << "transparent pixel not found!\n";
00643         return;
00644     }
00645 
00646     // Merge color tables
00647     int nc = src.numColors();
00648     src.setNumColors(nc + overlay.numColors());
00649     for (i=0; i<overlay.numColors(); i++)
00650     {
00651         src.setColor(nc+i, overlay.color(i));
00652     }
00653 
00654     // Overwrite nontransparent pixels.
00655     unsigned char *oline, *sline;
00656     for (i=0; i<src.height(); i++)
00657     {
00658         oline = overlay.scanLine(i);
00659         sline = src.scanLine(i);
00660         for (j=0; j<src.width(); j++)
00661         {
00662         if (oline[j] != trans)
00663             sline[j] = oline[j]+nc;
00664         }
00665     }
00666     }
00667 
00668     // Overlay at 32 bpp does use alpha blending
00669 
00670     if (src.depth() == 32)
00671     {
00672     QRgb *oline, *sline;
00673     int r1, g1, b1, a1;
00674     int r2, g2, b2, a2;
00675 
00676     for (i=0; i<src.height(); i++)
00677     {
00678         oline = (QRgb *) overlay.scanLine(i);
00679         sline = (QRgb *) src.scanLine(i);
00680 
00681         for (j=0; j<src.width(); j++)
00682         {
00683         r1 = tqRed(oline[j]);
00684         g1 = tqGreen(oline[j]);
00685         b1 = tqBlue(oline[j]);
00686         a1 = tqAlpha(oline[j]);
00687 
00688         r2 = tqRed(sline[j]);
00689         g2 = tqGreen(sline[j]);
00690         b2 = tqBlue(sline[j]);
00691         a2 = tqAlpha(sline[j]);
00692 
00693         r2 = (a1 * r1 + (0xff - a1) * r2) >> 8;
00694         g2 = (a1 * g1 + (0xff - a1) * g2) >> 8;
00695         b2 = (a1 * b1 + (0xff - a1) * b2) >> 8;
00696         a2 = TQMAX(a1, a2);
00697 
00698         sline[j] = tqRgba(r2, g2, b2, a2);
00699         }
00700     }
00701     }
00702 
00703     return;
00704 }
00705 
00706     void
00707 TDEIconEffect::visualActivate(TQWidget * widget, TQRect rect)
00708 {
00709     if (!TDEGlobalSettings::visualActivate())
00710         return;
00711 
00712     uint actSpeed = TDEGlobalSettings::visualActivateSpeed();
00713 
00714     uint actCount = TQMIN(rect.width(), rect.height()) / 2;
00715 
00716     // Clip actCount to range 1..10.
00717 
00718     if (actCount < 1)
00719         actCount = 1;
00720 
00721     else if (actCount > 10)
00722         actCount = 10;
00723 
00724     // Clip actSpeed to range 1..100.
00725 
00726     if (actSpeed < 1)
00727         actSpeed = 1;
00728 
00729     else if (actSpeed > 100)
00730         actSpeed = 100;
00731 
00732     // actSpeed needs to be converted to actDelay.
00733     // actDelay is inversely proportional to actSpeed and needs to be
00734     // divided up into actCount portions.
00735     // We also convert the us value to ms.
00736 
00737     unsigned int actDelay = (1000 * (100 - actSpeed)) / actCount;
00738 
00739     //kdDebug() << "actCount=" << actCount << " actDelay=" << actDelay << endl;
00740 
00741     TQPoint c = rect.center();
00742 
00743     TQPainter p(widget);
00744 
00745     // Use NotROP to avoid having to repaint the pixmap each time.
00746     p.setPen(TQPen(Qt::black, 2, Qt::DotLine));
00747     p.setRasterOp(TQt::NotROP);
00748 
00749     // The spacing between the rects we draw.
00750     // Use the minimum of width and height to avoid painting outside the
00751     // pixmap area.
00752     //unsigned int delta(TQMIN(rect.width() / actCount, rect.height() / actCount));
00753 
00754     // Support for rectangles by David
00755     unsigned int deltaX = rect.width() / actCount;
00756     unsigned int deltaY = rect.height() / actCount;
00757 
00758     for (unsigned int i = 1; i < actCount; i++) {
00759 
00760         int w = i * deltaX;
00761         int h = i * deltaY;
00762 
00763         rect.setRect(c.x() - w / 2, c.y() - h / 2, w, h);
00764 
00765         p.drawRect(rect);
00766         p.flush();
00767 
00768         usleep(actDelay);
00769 
00770         p.drawRect(rect);
00771     }
00772 }
00773 
00774 void
00775 TDEIconEffect::visualActivate(TQWidget * widget, TQRect rect, TQPixmap *pixmap)
00776 {
00777     if (!TDEGlobalSettings::visualActivate())
00778         return;
00779 
00780     // Image too big to display smoothly
00781     if ((rect.width() > 160) || (rect.height() > 160)) {
00782     visualActivate(widget, rect); // call old effect
00783     return;
00784     }
00785 
00786     uint actSpeed = TDEGlobalSettings::visualActivateSpeed();
00787     uint actCount = TQMIN(rect.width(), rect.height()) / 4;
00788 
00789 
00790     // Clip actCount to range 1..10.
00791     if (actCount < 1)
00792         actCount = 1;
00793 
00794     else if (actCount > 10)
00795         actCount = 10;
00796 
00797     // Clip actSpeed to range 1..100.
00798     if (actSpeed < 1)
00799         actSpeed = 1;
00800 
00801     else if (actSpeed > 100)
00802         actSpeed = 100;
00803 
00804     // actSpeed needs to be converted to actDelay.
00805     // actDelay is inversely proportional to actSpeed and needs to be
00806     // divided up into actCount portions.
00807     // We also convert the us value to ms.
00808 
00809     unsigned int actDelay = (1000 * (100 - actSpeed)) / actCount;
00810 
00811     unsigned int deltaX = rect.width() / actCount * 1.5;
00812     unsigned int deltaY = rect.height() / actCount * 1.5;
00813 
00814     TQPoint c = rect.center();
00815     TQRect maxRect(c.x() - (actCount * 2) * deltaX /2,
00816               c.y() - (actCount * 2) * deltaY /2,
00817           actCount * 2 * deltaX,
00818           actCount * 2 * deltaY);
00819 
00820     // convert rect to global coordinates if needed
00821     if ((widget->rect().width() <= maxRect.width())
00822        || (widget->rect().height() <= maxRect.height()))
00823     {
00824     TQPoint topLeft(rect.x(), rect.y());
00825     rect.moveLeft(widget->mapToGlobal(topLeft).x());
00826     rect.moveTop(widget->mapToGlobal(topLeft).y());
00827     c = rect.center();
00828     maxRect.setRect(c.x() - (actCount * 2) * deltaX /2,
00829                 c.y() - (actCount * 2) * deltaY /2,
00830             actCount * 2 * deltaX,
00831             actCount * 2 * deltaY);
00832     }
00833 
00834     TQPainter *p;
00835     TQImage img = pixmap->convertToImage();
00836     TQPixmap pix;
00837     TQPixmap composite(maxRect.width(), maxRect.height(), -1, TQPixmap::BestOptim);
00838     TQPainter cPainter(&composite);
00839     TQPoint cComposite = composite.rect().center();
00840 
00841     // enable alpha blending
00842     img.setAlphaBuffer(true);
00843     
00844     // Ugly hack... Get "Screenshot" to blt into and even do that on the
00845     // root window if the display area of <widget> is too small
00846     if ((widget->rect().width() <= maxRect.width())
00847        || (widget->rect().height() <= maxRect.height()))
00848     {
00849 //  p = new TQPainter(TQApplication::desktop()->screen( -1 ), TRUE);    // WARNING: This was done in Qt3.  It only worked in this placement due to a glitch in Qt3; it has therefore been moved below grabWidget, where it should have been in the first place.
00850     pix = TQPixmap::grabWindow((TQApplication::desktop()->screen( -1 ))->winId(),
00851                           maxRect.x(),
00852                       maxRect.y(),
00853                       maxRect.width(),
00854                       maxRect.height());
00855         p = new TQPainter(TQApplication::desktop()->screen( -1 ), TRUE);
00856     } else
00857     {
00858     // not as ugly as drawing directly to the screen
00859 //  p = new TQPainter(widget);  // WARNING: This was done in Qt3.  See above.
00860     pix = TQPixmap::grabWidget(widget,
00861                           maxRect.x(),
00862                       maxRect.y(),
00863                       maxRect.width(),
00864                       maxRect.height());
00865     p = new TQPainter(widget);
00866     }
00867     uchar deltaAlpha = 255 / (actCount * 1.2);
00868     
00869     // Activate effect like MacOS X
00870     for (unsigned int i = actCount; i < actCount * 2; i++) {
00871 
00872         int w = i * deltaX;
00873         int h = i * deltaY;
00874 
00875         rect.setRect(cComposite.x() - w / 2, cComposite.y() - h / 2, w, h);
00876 
00877     // draw offscreen
00878     cPainter.drawPixmap(0, 0, pix, 0, 0, pix.width(), pix.height());
00879     cPainter.drawImage(rect, img);
00880     cPainter.flush();
00881 
00882     // put onscreen
00883     p->drawPixmap(maxRect, composite);
00884         p->flush();
00885 
00886     // Fade out Icon a bit more
00887         int x, y;
00888         if ((img.depth() == 32) && tqt_use_xrender && tqt_has_xft)
00889         {
00890             int width  = img.width();
00891         int height = img.height();
00892     
00893         for (y=0; y<height; y++)
00894         {
00895 #ifdef WORDS_BIGENDIAN
00896         uchar *line = (uchar*) img.scanLine(y);
00897 #else
00898         uchar *line = (uchar*) img.scanLine(y) + 3;
00899 #endif
00900         for (x=0; x<width; x++)
00901         {
00902             *line = (*line < deltaAlpha) ? 0 : *line - deltaAlpha;
00903             line += 4;
00904         }
00905         }
00906     }
00907         usleep(actDelay*3);
00908     }
00909 
00910     // remove traces of the effect
00911     if ((widget->rect().width() <= maxRect.width())
00912        || (widget->rect().height() <= maxRect.height()))
00913     p->drawPixmap(maxRect, pix);
00914     else {
00915      p->drawPixmap(maxRect, pix);
00916         widget->update(rect);
00917     }
00918 
00919     delete p;
00920 }

tdecore

Skip menu "tdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.