19 #include <tqstringlist.h>
25 #include <tqpainter.h>
27 #include <tqapplication.h>
34 #include <kglobalsettings.h>
35 #include <kicontheme.h>
36 #include "kiconeffect.h"
38 #if defined(Q_WS_WIN) || defined(Q_WS_MACX)
39 static bool qt_use_xrender=
true;
40 static bool qt_has_xft=
true;
42 extern bool qt_use_xrender;
43 extern bool qt_has_xft;
45 class KIconEffectPrivate
49 TQColor mColor2[6][3];
54 d =
new KIconEffectPrivate;
58 KIconEffect::~KIconEffect()
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]);
191 TQImage
KIconEffect::apply(TQImage image,
int effect,
float value,
const TQColor col,
bool trans)
const
196 TQImage
KIconEffect::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.tqcolorTable();
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.tqcolorTable();
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.tqcolorTable();
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.tqcolorTable();
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.tqcolorTable();
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 (qt_use_xrender && qt_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 QRgb *line = (QRgb *) 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 ( qt_use_xrender && qt_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 QRgb *line = (QRgb *) img.scanLine(y);
534 QRgb 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 = (QRgb *) src.scanLine(y);
564 l2 = (QRgb *) 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";
604 if (!overlay.hasAlphaBuffer())
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++)
658 oline = overlay.scanLine(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)
676 for (i=0; i<src.height(); i++)
678 oline = (QRgb *) overlay.scanLine(i);
679 sline = (QRgb *) 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 = QMIN(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(Qt::black, 2, Qt::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) && qt_use_xrender && qt_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);
static void colorize(TQImage &image, const TQColor &col, float value)
Colorizes an image with a specific color.
double readDoubleNumEntry(const TQString &pKey, double nDefault=0.0) const
Reads a floating point value.
static void semiTransparent(TQImage &image)
Renders an image semi-transparent.
static void overlay(TQImage &src, TQImage &overlay)
Overlays an image with an other image.
TQImage apply(TQImage src, int group, int state) const
Applies an effect to an image.
Last state (last constant)
TQColor readColorEntry(const TQString &pKey, const TQColor *pDefault=0L) const
Reads a TQColor entry.
void setGroup(const TQString &group)
Specifies the group in which keys will be read and written.
TQString readEntry(const TQString &pKey, const TQString &aDefault=TQString::null) const
Reads the value of an entry specified by pKey in the current group.
KIconEffect()
Create a new KIconEffect.
static unsigned int visualActivateSpeed()
Returns the speed of the visual activation feedback.
bool readBoolEntry(const TQString &pKey, bool bDefault=false) const
Reads a boolean entry.
TQImage doublePixels(TQImage src) const
Returns an image twice as large, consisting of 2x2 pixels.
TQString fingerprint(int group, int state) const
Returns a fingerprint for the effect by encoding the given group and state into a TQString...
void init()
Rereads configuration.
static void toGamma(TQImage &image, float value)
Changes the gamma value of an image.
Helper class to facilitate working with KConfig / KSimpleConfig groups.
static TQColor baseColor()
Returns the default base (background) color.
Access KDE Configuration entries.
static void toGray(TQImage &image, float value)
Tints an image gray.
bool hasEffect(int group, int state) const
Tests whether an effect has been configured for the given icon group.
static void visualActivate(TQWidget *widget, TQRect rect)
Provides visual feedback to show activation of an icon on a widget.
static bool visualActivate()
Checks whether to show feedback when in item (specifically an icon) is activated. ...
static void deSaturate(TQImage &image, float value)
Desaturates an image.
static KConfig * config()
Returns the general config object.
static void toMonochrome(TQImage &image, const TQColor &black, const TQColor &white, float value)
Produces a monochrome icon with a given foreground and background color.