diff options
Diffstat (limited to 'tdecore/kiconeffect.cpp')
-rw-r--r-- | tdecore/kiconeffect.cpp | 920 |
1 files changed, 920 insertions, 0 deletions
diff --git a/tdecore/kiconeffect.cpp b/tdecore/kiconeffect.cpp new file mode 100644 index 000000000..9c76c7e4d --- /dev/null +++ b/tdecore/kiconeffect.cpp @@ -0,0 +1,920 @@ +/* vi: ts=8 sts=4 sw=4 + * $Id$ + * + * This file is part of the KDE project, module tdecore. + * Copyright (C) 2000 Geert Jansen <jansen@kde.org> + * with minor additions and based on ideas from + * Torsten Rahn <torsten@kde.org> + * + * This is free software; it comes under the GNU Library General + * Public License, version 2. See the file "COPYING.LIB" for the + * exact licensing terms. + */ + +#include <config.h> +#include <unistd.h> +#include <math.h> + +#include <tqstring.h> +#include <tqstringlist.h> +#include <tqbitmap.h> +#include <tqpixmap.h> +#include <tqimage.h> +#include <tqcolor.h> +#include <tqwidget.h> +#include <tqpainter.h> +#include <tqpen.h> +#include <tqapplication.h> +#include <tqpoint.h> +#include <tqrect.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <kconfig.h> +#include <kglobalsettings.h> +#include <kicontheme.h> +#include "kiconeffect.h" + +#if defined(Q_WS_WIN) || defined(Q_WS_MACX) +static bool qt_use_xrender=true; +static bool qt_has_xft=true; +#else +extern bool qt_use_xrender; +extern bool qt_has_xft; +#endif +class KIconEffectPrivate +{ +public: + TQString mKey[6][3]; + TQColor mColor2[6][3]; +}; + +KIconEffect::KIconEffect() +{ + d = new KIconEffectPrivate; + init(); +} + +KIconEffect::~KIconEffect() +{ + delete d; + d = 0L; +} + +void KIconEffect::init() +{ + KConfig *config = KGlobal::config(); + + int i, j, effect=-1; + TQStringList groups; + groups += "Desktop"; + groups += "Toolbar"; + groups += "MainToolbar"; + groups += "Small"; + groups += "Panel"; + + TQStringList states; + states += "Default"; + states += "Active"; + states += "Disabled"; + + TQStringList::ConstIterator it, it2; + TQString _togray("togray"); + TQString _colorize("colorize"); + TQString _desaturate("desaturate"); + TQString _togamma("togamma"); + TQString _none("none"); + TQString _tomonochrome("tomonochrome"); + + KConfigGroupSaver cs(config, "default"); + + for (it=groups.begin(), i=0; it!=groups.end(); it++, i++) + { + // Default effects + mEffect[i][0] = NoEffect; + mEffect[i][1] = ((i==0)||(i==4)) ? ToGamma : NoEffect; + mEffect[i][2] = ToGray; + + mTrans[i][0] = false; + mTrans[i][1] = false; + mTrans[i][2] = true; + mValue[i][0] = 1.0; + mValue[i][1] = ((i==0)||(i==4)) ? 0.7 : 1.0; + mValue[i][2] = 1.0; + mColor[i][0] = TQColor(144,128,248); + mColor[i][1] = TQColor(169,156,255); + mColor[i][2] = TQColor(34,202,0); + d->mColor2[i][0] = TQColor(0,0,0); + d->mColor2[i][1] = TQColor(0,0,0); + d->mColor2[i][2] = TQColor(0,0,0); + + config->setGroup(*it + "Icons"); + for (it2=states.begin(), j=0; it2!=states.end(); it2++, j++) + { + TQString tmp = config->readEntry(*it2 + "Effect"); + if (tmp == _togray) + effect = ToGray; + else if (tmp == _colorize) + effect = Colorize; + else if (tmp == _desaturate) + effect = DeSaturate; + else if (tmp == _togamma) + effect = ToGamma; + else if (tmp == _tomonochrome) + effect = ToMonochrome; + else if (tmp == _none) + effect = NoEffect; + else + continue; + if(effect != -1) + mEffect[i][j] = effect; + mValue[i][j] = config->readDoubleNumEntry(*it2 + "Value"); + mColor[i][j] = config->readColorEntry(*it2 + "Color"); + d->mColor2[i][j] = config->readColorEntry(*it2 + "Color2"); + mTrans[i][j] = config->readBoolEntry(*it2 + "SemiTransparent"); + + } + } +} + +bool KIconEffect::hasEffect(int group, int state) const +{ + return mEffect[group][state] != NoEffect; +} + +TQString KIconEffect::fingerprint(int group, int state) const +{ + if ( group >= KIcon::LastGroup ) return ""; + TQString cached = d->mKey[group][state]; + if (cached.isEmpty()) + { + TQString tmp; + cached = tmp.setNum(mEffect[group][state]); + cached += ':'; + cached += tmp.setNum(mValue[group][state]); + cached += ':'; + cached += mTrans[group][state] ? TQString::tqfromLatin1("trans") + : TQString::tqfromLatin1("notrans"); + if (mEffect[group][state] == Colorize || mEffect[group][state] == ToMonochrome) + { + cached += ':'; + cached += mColor[group][state].name(); + } + if (mEffect[group][state] == ToMonochrome) + { + cached += ':'; + cached += d->mColor2[group][state].name(); + } + + d->mKey[group][state] = cached; + } + + return cached; +} + +TQImage KIconEffect::apply(TQImage image, int group, int state) const +{ + if (state >= KIcon::LastState) + { + kdDebug(265) << "Illegal icon state: " << state << "\n"; + return image; + } + if (group >= KIcon::LastGroup) + { + kdDebug(265) << "Illegal icon group: " << group << "\n"; + return image; + } + return apply(image, mEffect[group][state], mValue[group][state], + mColor[group][state], d->mColor2[group][state], mTrans[group][state]); +} + +TQImage KIconEffect::apply(TQImage image, int effect, float value, const TQColor col, bool trans) const +{ + return apply (image, effect, value, col, KGlobalSettings::baseColor(), trans); +} + +TQImage KIconEffect::apply(TQImage image, int effect, float value, const TQColor col, const TQColor col2, bool trans) const +{ + if (effect >= LastEffect ) + { + kdDebug(265) << "Illegal icon effect: " << effect << "\n"; + return image; + } + if (value > 1.0) + value = 1.0; + else if (value < 0.0) + value = 0.0; + switch (effect) + { + case ToGray: + toGray(image, value); + break; + case DeSaturate: + deSaturate(image, value); + break; + case Colorize: + colorize(image, col, value); + break; + case ToGamma: + toGamma(image, value); + break; + case ToMonochrome: + toMonochrome(image, col, col2, value); + break; + } + if (trans == true) + { + semiTransparent(image); + } + return image; +} + +TQPixmap KIconEffect::apply(TQPixmap pixmap, int group, int state) const +{ + if (state >= KIcon::LastState) + { + kdDebug(265) << "Illegal icon state: " << state << "\n"; + return pixmap; + } + if (group >= KIcon::LastGroup) + { + kdDebug(265) << "Illegal icon group: " << group << "\n"; + return pixmap; + } + return apply(pixmap, mEffect[group][state], mValue[group][state], + mColor[group][state], d->mColor2[group][state], mTrans[group][state]); +} + +TQPixmap KIconEffect::apply(TQPixmap pixmap, int effect, float value, + const TQColor col, bool trans) const +{ + return apply (pixmap, effect, value, col, KGlobalSettings::baseColor(), trans); +} + +TQPixmap KIconEffect::apply(TQPixmap pixmap, int effect, float value, + const TQColor col, const TQColor col2, bool trans) const +{ + TQPixmap result; + + if (effect >= LastEffect ) + { + kdDebug(265) << "Illegal icon effect: " << effect << "\n"; + return result; + } + + if ((trans == true) && (effect == NoEffect)) + { + result = pixmap; + semiTransparent(result); + } + else if ( effect != NoEffect ) + { + TQImage tmpImg = pixmap.convertToImage(); + tmpImg = apply(tmpImg, effect, value, col, col2, trans); + result.convertFromImage(tmpImg); + } + else + result = pixmap; + + return result; +} + +// Taken from KImageEffect. We don't want to link tdecore to tdeui! As long +// as this code is not too big, it doesn't seem much of a problem to me. + +void KIconEffect::toGray(TQImage &img, float value) +{ + int pixels = (img.depth() > 8) ? img.width()*img.height() + : img.numColors(); + unsigned int *data = img.depth() > 8 ? (unsigned int *) img.bits() + : (unsigned int *) img.tqcolorTable(); + int rval, gval, bval, val, alpha, i; + for (i=0; i<pixels; i++) + { + val = tqGray(data[i]); + alpha = tqAlpha(data[i]); + if (value < 1.0) + { + rval = static_cast<int>(value*val+(1.0-value)*tqRed(data[i])); + gval = static_cast<int>(value*val+(1.0-value)*tqGreen(data[i])); + bval = static_cast<int>(value*val+(1.0-value)*tqBlue(data[i])); + data[i] = tqRgba(rval, gval, bval, alpha); + } else + data[i] = tqRgba(val, val, val, alpha); + } +} + +void KIconEffect::colorize(TQImage &img, const TQColor &col, float value) +{ + int pixels = (img.depth() > 8) ? img.width()*img.height() + : img.numColors(); + unsigned int *data = img.depth() > 8 ? (unsigned int *) img.bits() + : (unsigned int *) img.tqcolorTable(); + int rval, gval, bval, val, alpha, i; + float rcol = col.red(), gcol = col.green(), bcol = col.blue(); + for (i=0; i<pixels; i++) + { + val = tqGray(data[i]); + if (val < 128) + { + rval = static_cast<int>(rcol/128*val); + gval = static_cast<int>(gcol/128*val); + bval = static_cast<int>(bcol/128*val); + } + else if (val > 128) + { + rval = static_cast<int>((val-128)*(2-rcol/128)+rcol-1); + gval = static_cast<int>((val-128)*(2-gcol/128)+gcol-1); + bval = static_cast<int>((val-128)*(2-bcol/128)+bcol-1); + } + else // val == 128 + { + rval = static_cast<int>(rcol); + gval = static_cast<int>(gcol); + bval = static_cast<int>(bcol); + } + if (value < 1.0) + { + rval = static_cast<int>(value*rval+(1.0 - value)*tqRed(data[i])); + gval = static_cast<int>(value*gval+(1.0 - value)*tqGreen(data[i])); + bval = static_cast<int>(value*bval+(1.0 - value)*tqBlue(data[i])); + } + + alpha = tqAlpha(data[i]); + data[i] = tqRgba(rval, gval, bval, alpha); + } +} + +void KIconEffect::toMonochrome(TQImage &img, const TQColor &black, const TQColor &white, float value) { + int pixels = (img.depth() > 8) ? img.width()*img.height() : img.numColors(); + unsigned int *data = img.depth() > 8 ? (unsigned int *) img.bits() + : (unsigned int *) img.tqcolorTable(); + int rval, gval, bval, alpha, i; + int rw = white.red(), gw = white.green(), bw = white.blue(); + int rb = black.red(), gb = black.green(), bb = black.blue(); + + double values = 0, sum = 0; + bool grayscale = true; + // Step 1: determine the average brightness + for (i=0; i<pixels; i++) { + sum += tqGray(data[i])*tqAlpha(data[i]) + 255*(255-tqAlpha(data[i])); + values += 255; + if ((tqRed(data[i]) != tqGreen(data[i]) ) || (tqGreen(data[i]) != tqBlue(data[i]) )) + grayscale = false; + } + double medium = sum/values; + + // Step 2: Modify the image + if (grayscale) { + for (i=0; i<pixels; i++) { + int v = tqRed(data[i]); + rval = static_cast<int>( ((255-v)*rb + v*rw)*value/255 + (1.0-value)*tqRed(data[i])); + gval = static_cast<int>( ((255-v)*gb + v*gw)*value/255 + (1.0-value)*tqGreen(data[i])); + bval = static_cast<int>( ((255-v)*bb + v*bw)*value/255 + (1.0-value)*tqBlue(data[i])); + + alpha = tqAlpha(data[i]); + data[i] = tqRgba(rval, gval, bval, alpha); + } + } + else { + for (i=0; i<pixels; i++) { + if (tqGray(data[i]) <= medium) { + rval = static_cast<int>(value*rb+(1.0-value)*tqRed(data[i])); + gval = static_cast<int>(value*gb+(1.0-value)*tqGreen(data[i])); + bval = static_cast<int>(value*bb+(1.0-value)*tqBlue(data[i])); + } + else { + rval = static_cast<int>(value*rw+(1.0-value)*tqRed(data[i])); + gval = static_cast<int>(value*gw+(1.0-value)*tqGreen(data[i])); + bval = static_cast<int>(value*bw+(1.0-value)*tqBlue(data[i])); + } + + alpha = tqAlpha(data[i]); + data[i] = tqRgba(rval, gval, bval, alpha); + } + } +} + +void KIconEffect::deSaturate(TQImage &img, float value) +{ + int pixels = (img.depth() > 8) ? img.width()*img.height() + : img.numColors(); + unsigned int *data = (img.depth() > 8) ? (unsigned int *) img.bits() + : (unsigned int *) img.tqcolorTable(); + TQColor color; + int h, s, v, i; + for (i=0; i<pixels; i++) + { + color.setRgb(data[i]); + color.hsv(&h, &s, &v); + color.setHsv(h, (int) (s * (1.0 - value) + 0.5), v); + data[i] = tqRgba(color.red(), color.green(), color.blue(), + tqAlpha(data[i])); + } +} + +void KIconEffect::toGamma(TQImage &img, float value) +{ + int pixels = (img.depth() > 8) ? img.width()*img.height() + : img.numColors(); + unsigned int *data = (img.depth() > 8) ? (unsigned int *) img.bits() + : (unsigned int *) img.tqcolorTable(); + TQColor color; + int i, rval, gval, bval; + float gamma; + gamma = 1/(2*value+0.5); + + for (i=0; i<pixels; i++) + { + color.setRgb(data[i]); + color.rgb(&rval, &gval, &bval); + rval = static_cast<int>(pow(static_cast<float>(rval)/255 , gamma)*255); + gval = static_cast<int>(pow(static_cast<float>(gval)/255 , gamma)*255); + bval = static_cast<int>(pow(static_cast<float>(bval)/255 , gamma)*255); + data[i] = tqRgba(rval, gval, bval, tqAlpha(data[i])); + } +} + +void KIconEffect::semiTransparent(TQImage &img) +{ + img.setAlphaBuffer(true); + + int x, y; + if (img.depth() == 32) + { + int width = img.width(); + int height = img.height(); + + if (qt_use_xrender && qt_has_xft ) + for (y=0; y<height; y++) + { +#ifdef WORDS_BIGENDIAN + uchar *line = (uchar*) img.scanLine(y); +#else + uchar *line = (uchar*) img.scanLine(y) + 3; +#endif + for (x=0; x<width; x++) + { + *line >>= 1; + line += 4; + } + } + else + for (y=0; y<height; y++) + { + QRgb *line = (QRgb *) img.scanLine(y); + for (x=(y%2); x<width; x+=2) + line[x] &= 0x00ffffff; + } + + } else + { + // Insert transparent pixel into the clut. + int transColor = -1; + + // search for a color that is already transparent + for (x=0; x<img.numColors(); x++) + { + // try to find already transparent pixel + if (tqAlpha(img.color(x)) < 127) + { + transColor = x; + break; + } + } + + + // FIXME: image must have transparency + if(transColor < 0 || transColor >= img.numColors()) + return; + + img.setColor(transColor, 0); + if(img.depth() == 8) + { + for (y=0; y<img.height(); y++) + { + unsigned char *line = img.scanLine(y); + for (x=(y%2); x<img.width(); x+=2) + line[x] = transColor; + } + } + else + { + // SLOOW, but simple, as we would have to + // deal with endianess etc on our own here + for (y=0; y<img.height(); y++) + for (x=(y%2); x<img.width(); x+=2) + img.setPixel(x, y, transColor); + } + } +} + +void KIconEffect::semiTransparent(TQPixmap &pix) +{ + if ( qt_use_xrender && qt_has_xft ) + { + TQImage img=pix.convertToImage(); + semiTransparent(img); + pix.convertFromImage(img); + return; + } + + TQImage img; + if (pix.mask() != 0L) + img = pix.mask()->convertToImage(); + else + { + img.create(pix.size(), 1, 2, TQImage::BigEndian); + img.fill(1); + } + + for (int y=0; y<img.height(); y++) + { + QRgb *line = (QRgb *) img.scanLine(y); + QRgb pattern = (y % 2) ? 0x55555555 : 0xaaaaaaaa; + for (int x=0; x<(img.width()+31)/32; x++) + line[x] &= pattern; + } + TQBitmap mask; + mask.convertFromImage(img); + pix.setMask(mask); +} + +TQImage KIconEffect::doublePixels(TQImage src) const +{ + TQImage dst; + if (src.depth() == 1) + { + kdDebug(265) << "image depth 1 not supported\n"; + return dst; + } + + int w = src.width(); + int h = src.height(); + dst.create(w*2, h*2, src.depth()); + dst.setAlphaBuffer(src.hasAlphaBuffer()); + + int x, y; + if (src.depth() == 32) + { + QRgb *l1, *l2; + for (y=0; y<h; y++) + { + l1 = (QRgb *) src.scanLine(y); + l2 = (QRgb *) dst.scanLine(y*2); + for (x=0; x<w; x++) + { + l2[x*2] = l2[x*2+1] = l1[x]; + } + memcpy(dst.scanLine(y*2+1), l2, dst.bytesPerLine()); + } + } else + { + for (x=0; x<src.numColors(); x++) + dst.setColor(x, src.color(x)); + + unsigned char *l1, *l2; + for (y=0; y<h; y++) + { + l1 = src.scanLine(y); + l2 = dst.scanLine(y*2); + for (x=0; x<w; x++) + { + l2[x*2] = l1[x]; + l2[x*2+1] = l1[x]; + } + memcpy(dst.scanLine(y*2+1), l2, dst.bytesPerLine()); + } + } + return dst; +} + +void KIconEffect::overlay(TQImage &src, TQImage &overlay) +{ + if (src.depth() != overlay.depth()) + { + kdDebug(265) << "Image depth src != overlay!\n"; + return; + } + if (src.size() != overlay.size()) + { + kdDebug(265) << "Image size src != overlay\n"; + return; + } + if (!overlay.hasAlphaBuffer()) + { + kdDebug(265) << "Overlay doesn't have alpha buffer!\n"; + return; + } + + int i, j; + + // We don't do 1 bpp + + if (src.depth() == 1) + { + kdDebug(265) << "1bpp not supported!\n"; + return; + } + + // Overlay at 8 bpp doesn't use alpha blending + + if (src.depth() == 8) + { + if (src.numColors() + overlay.numColors() > 255) + { + kdDebug(265) << "Too many colors in src + overlay!\n"; + return; + } + + // Find transparent pixel in overlay + int trans; + for (trans=0; trans<overlay.numColors(); trans++) + { + if (tqAlpha(overlay.color(trans)) == 0) + { + kdDebug(265) << "transparent pixel found at " << trans << "\n"; + break; + } + } + if (trans == overlay.numColors()) + { + kdDebug(265) << "transparent pixel not found!\n"; + return; + } + + // Merge color tables + int nc = src.numColors(); + src.setNumColors(nc + overlay.numColors()); + for (i=0; i<overlay.numColors(); i++) + { + src.setColor(nc+i, overlay.color(i)); + } + + // Overwrite nontransparent pixels. + unsigned char *oline, *sline; + for (i=0; i<src.height(); i++) + { + oline = overlay.scanLine(i); + sline = src.scanLine(i); + for (j=0; j<src.width(); j++) + { + if (oline[j] != trans) + sline[j] = oline[j]+nc; + } + } + } + + // Overlay at 32 bpp does use alpha blending + + if (src.depth() == 32) + { + QRgb *oline, *sline; + int r1, g1, b1, a1; + int r2, g2, b2, a2; + + for (i=0; i<src.height(); i++) + { + oline = (QRgb *) overlay.scanLine(i); + sline = (QRgb *) src.scanLine(i); + + for (j=0; j<src.width(); j++) + { + r1 = tqRed(oline[j]); + g1 = tqGreen(oline[j]); + b1 = tqBlue(oline[j]); + a1 = tqAlpha(oline[j]); + + r2 = tqRed(sline[j]); + g2 = tqGreen(sline[j]); + b2 = tqBlue(sline[j]); + a2 = tqAlpha(sline[j]); + + r2 = (a1 * r1 + (0xff - a1) * r2) >> 8; + g2 = (a1 * g1 + (0xff - a1) * g2) >> 8; + b2 = (a1 * b1 + (0xff - a1) * b2) >> 8; + a2 = QMAX(a1, a2); + + sline[j] = tqRgba(r2, g2, b2, a2); + } + } + } + + return; +} + + void +KIconEffect::visualActivate(TQWidget * widget, TQRect rect) +{ + if (!KGlobalSettings::visualActivate()) + return; + + uint actSpeed = KGlobalSettings::visualActivateSpeed(); + + uint actCount = QMIN(rect.width(), rect.height()) / 2; + + // Clip actCount to range 1..10. + + if (actCount < 1) + actCount = 1; + + else if (actCount > 10) + actCount = 10; + + // Clip actSpeed to range 1..100. + + if (actSpeed < 1) + actSpeed = 1; + + else if (actSpeed > 100) + actSpeed = 100; + + // actSpeed needs to be converted to actDelay. + // actDelay is inversely proportional to actSpeed and needs to be + // divided up into actCount portions. + // We also convert the us value to ms. + + unsigned int actDelay = (1000 * (100 - actSpeed)) / actCount; + + //kdDebug() << "actCount=" << actCount << " actDelay=" << actDelay << endl; + + TQPoint c = rect.center(); + + TQPainter p(widget); + + // Use NotROP to avoid having to tqrepaint the pixmap each time. + p.setPen(TQPen(Qt::black, 2, Qt::DotLine)); + p.setRasterOp(TQt::NotROP); + + // The spacing between the rects we draw. + // Use the minimum of width and height to avoid painting outside the + // pixmap area. + //unsigned int delta(QMIN(rect.width() / actCount, rect.height() / actCount)); + + // Support for rectangles by David + unsigned int deltaX = rect.width() / actCount; + unsigned int deltaY = rect.height() / actCount; + + for (unsigned int i = 1; i < actCount; i++) { + + int w = i * deltaX; + int h = i * deltaY; + + rect.setRect(c.x() - w / 2, c.y() - h / 2, w, h); + + p.drawRect(rect); + p.flush(); + + usleep(actDelay); + + p.drawRect(rect); + } +} + +void +KIconEffect::visualActivate(TQWidget * widget, TQRect rect, TQPixmap *pixmap) +{ + if (!KGlobalSettings::visualActivate()) + return; + + // Image too big to display smoothly + if ((rect.width() > 160) || (rect.height() > 160)) { + visualActivate(widget, rect); // call old effect + return; + } + + uint actSpeed = KGlobalSettings::visualActivateSpeed(); + uint actCount = TQMIN(rect.width(), rect.height()) / 4; + + + // Clip actCount to range 1..10. + if (actCount < 1) + actCount = 1; + + else if (actCount > 10) + actCount = 10; + + // Clip actSpeed to range 1..100. + if (actSpeed < 1) + actSpeed = 1; + + else if (actSpeed > 100) + actSpeed = 100; + + // actSpeed needs to be converted to actDelay. + // actDelay is inversely proportional to actSpeed and needs to be + // divided up into actCount portions. + // We also convert the us value to ms. + + unsigned int actDelay = (1000 * (100 - actSpeed)) / actCount; + + unsigned int deltaX = rect.width() / actCount * 1.5; + unsigned int deltaY = rect.height() / actCount * 1.5; + + TQPoint c = rect.center(); + TQRect maxRect(c.x() - (actCount * 2) * deltaX /2, + c.y() - (actCount * 2) * deltaY /2, + actCount * 2 * deltaX, + actCount * 2 * deltaY); + + // convert rect to global coordinates if needed + if ((widget->rect().width() <= maxRect.width()) + || (widget->rect().height() <= maxRect.height())) + { + TQPoint topLeft(rect.x(), rect.y()); + rect.moveLeft(widget->mapToGlobal(topLeft).x()); + rect.moveTop(widget->mapToGlobal(topLeft).y()); + c = rect.center(); + maxRect.setRect(c.x() - (actCount * 2) * deltaX /2, + c.y() - (actCount * 2) * deltaY /2, + actCount * 2 * deltaX, + actCount * 2 * deltaY); + } + + TQPainter *p; + TQImage img = pixmap->convertToImage(); + TQPixmap pix; + TQPixmap composite(maxRect.width(), maxRect.height(), -1, TQPixmap::BestOptim); + TQPainter cPainter(&composite); + TQPoint cComposite = composite.rect().center(); + + // enable alpha blending + img.setAlphaBuffer(true); + + // Ugly hack... Get "Screenshot" to blt into and even do that on the + // root window if the display area of <widget> is too small + if ((widget->rect().width() <= maxRect.width()) + || (widget->rect().height() <= maxRect.height())) + { +// 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. + pix = TQPixmap::grabWindow((TQApplication::desktop()->screen( -1 ))->winId(), + maxRect.x(), + maxRect.y(), + maxRect.width(), + maxRect.height()); + p = new TQPainter(TQApplication::desktop()->screen( -1 ), TRUE); + } else + { + // not as ugly as drawing directly to the screen +// p = new TQPainter(widget); // WARNING: This was done in Qt3. See above. + pix = TQPixmap::grabWidget(widget, + maxRect.x(), + maxRect.y(), + maxRect.width(), + maxRect.height()); + p = new TQPainter(widget); + } + uchar deltaAlpha = 255 / (actCount * 1.2); + + // Activate effect like MacOS X + for (unsigned int i = actCount; i < actCount * 2; i++) { + + int w = i * deltaX; + int h = i * deltaY; + + rect.setRect(cComposite.x() - w / 2, cComposite.y() - h / 2, w, h); + + // draw offscreen + cPainter.drawPixmap(0, 0, pix, 0, 0, pix.width(), pix.height()); + cPainter.drawImage(rect, img); + cPainter.flush(); + + // put onscreen + p->drawPixmap(maxRect, composite); + p->flush(); + + // Fade out Icon a bit more + int x, y; + if ((img.depth() == 32) && qt_use_xrender && qt_has_xft) + { + int width = img.width(); + int height = img.height(); + + for (y=0; y<height; y++) + { +#ifdef WORDS_BIGENDIAN + uchar *line = (uchar*) img.scanLine(y); +#else + uchar *line = (uchar*) img.scanLine(y) + 3; +#endif + for (x=0; x<width; x++) + { + *line = (*line < deltaAlpha) ? 0 : *line - deltaAlpha; + line += 4; + } + } + } + usleep(actDelay*3); + } + + // remove traces of the effect + if ((widget->rect().width() <= maxRect.width()) + || (widget->rect().height() <= maxRect.height())) + p->drawPixmap(maxRect, pix); + else { + p->drawPixmap(maxRect, pix); + widget->update(rect); + } + + delete p; +} |