19#include <tqstringlist.h>
27#include <tqapplication.h>
34#include <tdeglobalsettings.h>
35#include <kicontheme.h>
36#include "kiconeffect.h"
38#if defined(TQ_WS_WIN) || defined(TQ_WS_MACX)
39static bool tqt_use_xrender=
true;
40static bool tqt_has_xft=
true;
42extern bool tqt_use_xrender;
43extern bool tqt_has_xft;
45class TDEIconEffectPrivate
49 TQColor mColor2[6][3];
54 d =
new TDEIconEffectPrivate;
58TDEIconEffect::~TDEIconEffect()
72 groups +=
"MainToolbar";
81 TQStringList::ConstIterator it, it2;
82 TQString _togray(
"togray");
83 TQString _colorize(
"colorize");
84 TQString _desaturate(
"desaturate");
85 TQString _togamma(
"togamma");
86 TQString _none(
"none");
87 TQString _tomonochrome(
"tomonochrome");
91 for (it=groups.begin(), i=0; it!=groups.end(); it++, i++)
94 mEffect[i][0] = NoEffect;
95 mEffect[i][1] = ((i==0)||(i==4)) ? ToGamma : NoEffect;
96 mEffect[i][2] = ToGray;
102 mValue[i][1] = ((i==0)||(i==4)) ? 0.7 : 1.0;
104 mColor[i][0] = TQColor(144,128,248);
105 mColor[i][1] = TQColor(169,156,255);
106 mColor[i][2] = TQColor(34,202,0);
107 d->mColor2[i][0] = TQColor(0,0,0);
108 d->mColor2[i][1] = TQColor(0,0,0);
109 d->mColor2[i][2] = TQColor(0,0,0);
112 for (it2=states.begin(), j=0; it2!=states.end(); it2++, j++)
114 TQString tmp = config->
readEntry(*it2 +
"Effect");
117 else if (tmp == _colorize)
119 else if (tmp == _desaturate)
121 else if (tmp == _togamma)
123 else if (tmp == _tomonochrome)
125 else if (tmp == _none)
130 mEffect[i][j] = effect;
134 mTrans[i][j] = config->
readBoolEntry(*it2 +
"SemiTransparent");
142 return mEffect[group][state] != NoEffect;
148 TQString cached = d->mKey[group][state];
149 if (cached.isEmpty())
152 cached = tmp.setNum(mEffect[group][state]);
154 cached += tmp.setNum(mValue[group][state]);
156 cached += mTrans[group][state] ? TQString::fromLatin1(
"trans")
157 : TQString::fromLatin1(
"notrans");
158 if (mEffect[group][state] == Colorize || mEffect[group][state] ==
ToMonochrome)
161 cached += mColor[group][state].name();
166 cached += d->mColor2[group][state].name();
169 d->mKey[group][state] = cached;
179 kdDebug(265) <<
"Illegal icon state: " << state <<
"\n";
184 kdDebug(265) <<
"Illegal icon group: " << group <<
"\n";
187 return apply(image, mEffect[group][state], mValue[group][state],
188 mColor[group][state], d->mColor2[group][state], mTrans[group][state]);
196TQImage
TDEIconEffect::apply(TQImage image,
int effect,
float value,
const TQColor col,
const TQColor col2,
bool trans)
const
198 if (effect >= LastEffect )
200 kdDebug(265) <<
"Illegal icon effect: " << effect <<
"\n";
205 else if (value < 0.0)
236 kdDebug(265) <<
"Illegal icon state: " << state <<
"\n";
241 kdDebug(265) <<
"Illegal icon group: " << group <<
"\n";
244 return apply(pixmap, mEffect[group][state], mValue[group][state],
245 mColor[group][state], d->mColor2[group][state], mTrans[group][state]);
249 const TQColor col,
bool trans)
const
255 const TQColor col,
const TQColor col2,
bool trans)
const
259 if (effect >= LastEffect )
261 kdDebug(265) <<
"Illegal icon effect: " << effect <<
"\n";
265 if ((trans ==
true) && (effect == NoEffect))
270 else if ( effect != NoEffect )
272 TQImage tmpImg = pixmap.convertToImage();
273 tmpImg =
apply(tmpImg, effect, value, col, col2, trans);
274 result.convertFromImage(tmpImg);
287 int pixels = (img.depth() > 8) ? img.width()*img.height()
289 unsigned int *data = img.depth() > 8 ? (
unsigned int *) img.bits()
290 : (
unsigned int *) img.colorTable();
291 int rval, gval, bval, val, alpha, i;
292 for (i=0; i<pixels; i++)
294 val = tqGray(data[i]);
295 alpha = tqAlpha(data[i]);
298 rval =
static_cast<int>(value*val+(1.0-value)*tqRed(data[i]));
299 gval =
static_cast<int>(value*val+(1.0-value)*tqGreen(data[i]));
300 bval =
static_cast<int>(value*val+(1.0-value)*tqBlue(data[i]));
301 data[i] = tqRgba(rval, gval, bval, alpha);
303 data[i] = tqRgba(val, val, val, alpha);
309 int pixels = (img.depth() > 8) ? img.width()*img.height()
311 unsigned int *data = img.depth() > 8 ? (
unsigned int *) img.bits()
312 : (
unsigned int *) img.colorTable();
313 int rval, gval, bval, val, alpha, i;
314 float rcol = col.red(), gcol = col.green(), bcol = col.blue();
315 for (i=0; i<pixels; i++)
317 val = tqGray(data[i]);
320 rval =
static_cast<int>(rcol/128*val);
321 gval =
static_cast<int>(gcol/128*val);
322 bval =
static_cast<int>(bcol/128*val);
326 rval =
static_cast<int>((val-128)*(2-rcol/128)+rcol-1);
327 gval =
static_cast<int>((val-128)*(2-gcol/128)+gcol-1);
328 bval =
static_cast<int>((val-128)*(2-bcol/128)+bcol-1);
332 rval =
static_cast<int>(rcol);
333 gval =
static_cast<int>(gcol);
334 bval =
static_cast<int>(bcol);
338 rval =
static_cast<int>(value*rval+(1.0 - value)*tqRed(data[i]));
339 gval =
static_cast<int>(value*gval+(1.0 - value)*tqGreen(data[i]));
340 bval =
static_cast<int>(value*bval+(1.0 - value)*tqBlue(data[i]));
343 alpha = tqAlpha(data[i]);
344 data[i] = tqRgba(rval, gval, bval, alpha);
349 int pixels = (img.depth() > 8) ? img.width()*img.height() : img.numColors();
350 unsigned int *data = img.depth() > 8 ? (
unsigned int *) img.bits()
351 : (
unsigned int *) img.colorTable();
352 int rval, gval, bval, alpha, i;
353 int rw = white.red(), gw = white.green(), bw = white.blue();
354 int rb = black.red(), gb = black.green(), bb = black.blue();
356 double values = 0, sum = 0;
357 bool grayscale =
true;
359 for (i=0; i<pixels; i++) {
360 sum += tqGray(data[i])*tqAlpha(data[i]) + 255*(255-tqAlpha(data[i]));
362 if ((tqRed(data[i]) != tqGreen(data[i]) ) || (tqGreen(data[i]) != tqBlue(data[i]) ))
365 double medium = sum/values;
369 for (i=0; i<pixels; i++) {
370 int v = tqRed(data[i]);
371 rval =
static_cast<int>( ((255-v)*rb + v*rw)*value/255 + (1.0-value)*tqRed(data[i]));
372 gval =
static_cast<int>( ((255-v)*gb + v*gw)*value/255 + (1.0-value)*tqGreen(data[i]));
373 bval =
static_cast<int>( ((255-v)*bb + v*bw)*value/255 + (1.0-value)*tqBlue(data[i]));
375 alpha = tqAlpha(data[i]);
376 data[i] = tqRgba(rval, gval, bval, alpha);
380 for (i=0; i<pixels; i++) {
381 if (tqGray(data[i]) <= medium) {
382 rval =
static_cast<int>(value*rb+(1.0-value)*tqRed(data[i]));
383 gval =
static_cast<int>(value*gb+(1.0-value)*tqGreen(data[i]));
384 bval =
static_cast<int>(value*bb+(1.0-value)*tqBlue(data[i]));
387 rval =
static_cast<int>(value*rw+(1.0-value)*tqRed(data[i]));
388 gval =
static_cast<int>(value*gw+(1.0-value)*tqGreen(data[i]));
389 bval =
static_cast<int>(value*bw+(1.0-value)*tqBlue(data[i]));
392 alpha = tqAlpha(data[i]);
393 data[i] = tqRgba(rval, gval, bval, alpha);
400 int pixels = (img.depth() > 8) ? img.width()*img.height()
402 unsigned int *data = (img.depth() > 8) ? (
unsigned int *) img.bits()
403 : (
unsigned int *) img.colorTable();
406 for (i=0; i<pixels; i++)
408 color.setRgb(data[i]);
409 color.hsv(&h, &s, &v);
410 color.setHsv(h, (
int) (s * (1.0 - value) + 0.5), v);
411 data[i] = tqRgba(color.red(), color.green(), color.blue(),
418 int pixels = (img.depth() > 8) ? img.width()*img.height()
420 unsigned int *data = (img.depth() > 8) ? (
unsigned int *) img.bits()
421 : (
unsigned int *) img.colorTable();
423 int i, rval, gval, bval;
425 gamma = 1/(2*value+0.5);
427 for (i=0; i<pixels; i++)
429 color.setRgb(data[i]);
430 color.rgb(&rval, &gval, &bval);
431 rval =
static_cast<int>(pow(
static_cast<float>(rval)/255 , gamma)*255);
432 gval =
static_cast<int>(pow(
static_cast<float>(gval)/255 , gamma)*255);
433 bval =
static_cast<int>(pow(
static_cast<float>(bval)/255 , gamma)*255);
434 data[i] = tqRgba(rval, gval, bval, tqAlpha(data[i]));
440 img.setAlphaBuffer(
true);
443 if (img.depth() == 32)
445 int width = img.width();
446 int height = img.height();
448 if (tqt_use_xrender && tqt_has_xft )
449 for (y=0; y<height; y++)
451#ifdef WORDS_BIGENDIAN
452 uchar *line = (uchar*) img.scanLine(y);
454 uchar *line = (uchar*) img.scanLine(y) + 3;
456 for (x=0; x<width; x++)
463 for (y=0; y<height; y++)
465 TQRgb *line = (TQRgb *) img.scanLine(y);
466 for (x=(y%2); x<width; x+=2)
467 line[x] &= 0x00ffffff;
476 for (x=0; x<img.numColors(); x++)
479 if (tqAlpha(img.color(x)) < 127)
488 if(transColor < 0 || transColor >= img.numColors())
491 img.setColor(transColor, 0);
494 for (y=0; y<img.height(); y++)
496 unsigned char *line = img.scanLine(y);
497 for (x=(y%2); x<img.width(); x+=2)
498 line[x] = transColor;
505 for (y=0; y<img.height(); y++)
506 for (x=(y%2); x<img.width(); x+=2)
507 img.setPixel(x, y, transColor);
514 if ( tqt_use_xrender && tqt_has_xft )
516 TQImage img=pix.convertToImage();
518 pix.convertFromImage(img);
523 if (pix.mask() != 0L)
524 img = pix.mask()->convertToImage();
527 img.create(pix.size(), 1, 2, TQImage::BigEndian);
531 for (
int y=0; y<img.height(); y++)
533 TQRgb *line = (TQRgb *) img.scanLine(y);
534 TQRgb pattern = (y % 2) ? 0x55555555 : 0xaaaaaaaa;
535 for (
int x=0; x<(img.width()+31)/32; x++)
539 mask.convertFromImage(img);
546 if (src.depth() == 1)
548 kdDebug(265) <<
"image depth 1 not supported\n";
553 int h = src.height();
554 dst.create(w*2, h*2, src.depth());
555 dst.setAlphaBuffer(src.hasAlphaBuffer());
558 if (src.depth() == 32)
563 l1 = (TQRgb *) src.scanLine(y);
564 l2 = (TQRgb *) dst.scanLine(y*2);
567 l2[x*2] = l2[x*2+1] = l1[x];
569 memcpy(dst.scanLine(y*2+1), l2, dst.bytesPerLine());
573 for (x=0; x<src.numColors(); x++)
574 dst.setColor(x, src.color(x));
576 unsigned char *l1, *l2;
579 l1 = src.scanLine(y);
580 l2 = dst.scanLine(y*2);
586 memcpy(dst.scanLine(y*2+1), l2, dst.bytesPerLine());
594 if (src.depth() !=
overlay.depth())
596 kdDebug(265) <<
"Image depth src != overlay!\n";
599 if (src.size() !=
overlay.size())
601 kdDebug(265) <<
"Image size src != overlay\n";
606 kdDebug(265) <<
"Overlay doesn't have alpha buffer!\n";
614 if (src.depth() == 1)
616 kdDebug(265) <<
"1bpp not supported!\n";
622 if (src.depth() == 8)
624 if (src.numColors() +
overlay.numColors() > 255)
626 kdDebug(265) <<
"Too many colors in src + overlay!\n";
632 for (trans=0; trans<
overlay.numColors(); trans++)
634 if (tqAlpha(
overlay.color(trans)) == 0)
636 kdDebug(265) <<
"transparent pixel found at " << trans <<
"\n";
640 if (trans ==
overlay.numColors())
642 kdDebug(265) <<
"transparent pixel not found!\n";
647 int nc = src.numColors();
648 src.setNumColors(nc +
overlay.numColors());
649 for (i=0; i<
overlay.numColors(); i++)
651 src.setColor(nc+i,
overlay.color(i));
655 unsigned char *oline, *sline;
656 for (i=0; i<src.height(); i++)
659 sline = src.scanLine(i);
660 for (j=0; j<src.width(); j++)
662 if (oline[j] != trans)
663 sline[j] = oline[j]+nc;
670 if (src.depth() == 32)
672 TQRgb *oline, *sline;
676 for (i=0; i<src.height(); i++)
678 oline = (TQRgb *)
overlay.scanLine(i);
679 sline = (TQRgb *) src.scanLine(i);
681 for (j=0; j<src.width(); j++)
683 r1 = tqRed(oline[j]);
684 g1 = tqGreen(oline[j]);
685 b1 = tqBlue(oline[j]);
686 a1 = tqAlpha(oline[j]);
688 r2 = tqRed(sline[j]);
689 g2 = tqGreen(sline[j]);
690 b2 = tqBlue(sline[j]);
691 a2 = tqAlpha(sline[j]);
693 r2 = (a1 * r1 + (0xff - a1) * r2) >> 8;
694 g2 = (a1 * g1 + (0xff - a1) * g2) >> 8;
695 b2 = (a1 * b1 + (0xff - a1) * b2) >> 8;
698 sline[j] = tqRgba(r2, g2, b2, a2);
714 uint actCount = TQMIN(rect.width(), rect.height()) / 2;
721 else if (actCount > 10)
729 else if (actSpeed > 100)
737 unsigned int actDelay = (1000 * (100 - actSpeed)) / actCount;
741 TQPoint c = rect.center();
746 p.setPen(TQPen(TQt::black, 2, TQt::DotLine));
747 p.setRasterOp(TQt::NotROP);
755 unsigned int deltaX = rect.width() / actCount;
756 unsigned int deltaY = rect.height() / actCount;
758 for (
unsigned int i = 1; i < actCount; i++) {
763 rect.setRect(c.x() - w / 2, c.y() - h / 2, w, h);
781 if ((rect.width() > 160) || (rect.height() > 160)) {
787 uint actCount = TQMIN(rect.width(), rect.height()) / 4;
794 else if (actCount > 10)
801 else if (actSpeed > 100)
809 unsigned int actDelay = (1000 * (100 - actSpeed)) / actCount;
811 unsigned int deltaX = rect.width() / actCount * 1.5;
812 unsigned int deltaY = rect.height() / actCount * 1.5;
814 TQPoint c = rect.center();
815 TQRect maxRect(c.x() - (actCount * 2) * deltaX /2,
816 c.y() - (actCount * 2) * deltaY /2,
817 actCount * 2 * deltaX,
818 actCount * 2 * deltaY);
821 if ((widget->rect().width() <= maxRect.width())
822 || (widget->rect().height() <= maxRect.height()))
824 TQPoint topLeft(rect.x(), rect.y());
825 rect.moveLeft(widget->mapToGlobal(topLeft).x());
826 rect.moveTop(widget->mapToGlobal(topLeft).y());
828 maxRect.setRect(c.x() - (actCount * 2) * deltaX /2,
829 c.y() - (actCount * 2) * deltaY /2,
830 actCount * 2 * deltaX,
831 actCount * 2 * deltaY);
835 TQImage img = pixmap->convertToImage();
837 TQPixmap composite(maxRect.width(), maxRect.height(), -1, TQPixmap::BestOptim);
838 TQPainter cPainter(&composite);
839 TQPoint cComposite = composite.rect().center();
842 img.setAlphaBuffer(
true);
846 if ((widget->rect().width() <= maxRect.width())
847 || (widget->rect().height() <= maxRect.height()))
850 pix = TQPixmap::grabWindow((TQApplication::desktop()->screen( -1 ))->winId(),
855 p =
new TQPainter(TQApplication::desktop()->screen( -1 ), TRUE);
860 pix = TQPixmap::grabWidget(widget,
865 p =
new TQPainter(widget);
867 uchar deltaAlpha = 255 / (actCount * 1.2);
870 for (
unsigned int i = actCount; i < actCount * 2; i++) {
875 rect.setRect(cComposite.x() - w / 2, cComposite.y() - h / 2, w, h);
878 cPainter.drawPixmap(0, 0, pix, 0, 0, pix.width(), pix.height());
879 cPainter.drawImage(rect, img);
883 p->drawPixmap(maxRect, composite);
888 if ((img.depth() == 32) && tqt_use_xrender && tqt_has_xft)
890 int width = img.width();
891 int height = img.height();
893 for (y=0; y<height; y++)
895#ifdef WORDS_BIGENDIAN
896 uchar *line = (uchar*) img.scanLine(y);
898 uchar *line = (uchar*) img.scanLine(y) + 3;
900 for (x=0; x<width; x++)
902 *line = (*line < deltaAlpha) ? 0 : *line - deltaAlpha;
911 if ((widget->rect().width() <= maxRect.width())
912 || (widget->rect().height() <= maxRect.height()))
913 p->drawPixmap(maxRect, pix);
915 p->drawPixmap(maxRect, pix);
916 widget->update(rect);
TQString readEntry(const TQString &pKey, const TQString &aDefault=TQString::null) const
Reads the value of an entry specified by pKey in the current group.
TQColor readColorEntry(const TQString &pKey, const TQColor *pDefault=0L) const
Reads a TQColor entry.
bool readBoolEntry(const TQString &pKey, bool bDefault=false) const
Reads a boolean entry.
double readDoubleNumEntry(const TQString &pKey, double nDefault=0.0) const
Reads a floating point value.
void setGroup(const TQString &group)
Specifies the group in which keys will be read and written.
Helper class to facilitate working with TDEConfig / KSimpleConfig groups.
Access KDE Configuration entries.
static TQColor baseColor()
Returns the default base (background) color.
static unsigned int visualActivateSpeed()
Returns the speed of the visual activation feedback.
static bool visualActivate()
Checks whether to show feedback when in item (specifically an icon) is activated.
static TDEConfig * config()
Returns the general config object.
void init()
Rereads configuration.
static void toMonochrome(TQImage &image, const TQColor &black, const TQColor &white, float value)
Produces a monochrome icon with a given foreground and background color.
static void toGray(TQImage &image, float value)
Tints an image gray.
TQImage doublePixels(TQImage src) const
Returns an image twice as large, consisting of 2x2 pixels.
bool hasEffect(int group, int state) const
Tests whether an effect has been configured for the given icon group.
static void overlay(TQImage &src, TQImage &overlay)
Overlays an image with an other image.
static void deSaturate(TQImage &image, float value)
Desaturates an image.
static void colorize(TQImage &image, const TQColor &col, float value)
Colorizes an image with a specific color.
static void toGamma(TQImage &image, float value)
Changes the gamma value of an image.
TDEIconEffect()
Create a new TDEIconEffect.
static void semiTransparent(TQImage &image)
Renders an image semi-transparent.
TQImage apply(TQImage src, int group, int state) const
Applies an effect to an image.
TQString fingerprint(int group, int state) const
Returns a fingerprint for the effect by encoding the given group and state into a TQString.
static void visualActivate(TQWidget *widget, TQRect rect)
Provides visual feedback to show activation of an icon on a widget.
@ LastState
Last state (last constant)