Warning--
[kdeartwork.git] / kscreensaver / kdesavers / science.cpp
blob185f3b554ee74967d82a4a07960301cfc8cc1e9f
1 //-----------------------------------------------------------------------------
2 //
3 // kscience - screen saver for KDE
4 //
5 // Copyright (c) Rene Beutler 1998
6 //
8 #include <config.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <math.h>
12 #include <sys/types.h>
13 #include <time.h>
15 #include <qpainter.h>
16 #include <qpixmap.h>
17 #include <qlabel.h>
18 #include <qlistbox.h>
19 #include <qcheckbox.h>
20 #include <qslider.h>
21 #include <qlayout.h>
23 #include <kapplication.h>
24 #include <kglobal.h>
25 #include <kmessagebox.h>
26 #include <klocale.h>
27 #include <kconfig.h>
28 #include <kstandarddirs.h>
29 #include <krandomsequence.h>
31 #include "science.h"
32 #include "science.moc"
34 #if defined Q_WS_X11 && !defined K_WS_QTONLY
35 #include <X11/Xlib.h>
36 #include <X11/Xutil.h>
37 #endif
39 #define SCI_DEFAULT_MODE 0
40 #define SCI_DEFAULT_MOVEX 6
41 #define SCI_DEFAULT_MOVEY 8
42 #define SCI_DEFAULT_SIZE 15
43 #define SCI_DEFAULT_INTENSITY 4
44 #define SCI_DEFAULT_SPEED 70
45 #define SCI_DEFAULT_INVERSE false
46 #define SCI_DEFAULT_GRAVITY false
47 #define SCI_DEFAULT_HIDE false
48 #define SCI_MAX_SPEED 100
49 #define SCI_MAX_MOVE 20
51 #undef Below
54 // libkscreensaver interface
55 extern "C"
57 KDE_EXPORT const char *kss_applicationName = "kscience.kss";
58 KDE_EXPORT const char *kss_description = I18N_NOOP( "Science Screen Saver" );
59 KDE_EXPORT const char *kss_version = "2.2.0";
61 KDE_EXPORT KScreenSaver *kss_create( WId id )
63 return new KScienceSaver( id );
66 KDE_EXPORT QDialog *kss_setup()
68 return new KScienceSetup();
72 static struct {
73 QString name;
74 bool inverseEnable;
75 } modeInfo[MAX_MODES];
77 enum { MODE_WHIRL=0, MODE_CURVATURE, MODE_SPHERE, MODE_WAVE, MODE_EXPONENTIAL, MODE_CONTRACTION };
79 void initModeInfo()
81 modeInfo[MODE_WHIRL].name = i18n( "Whirl" );
82 modeInfo[MODE_WHIRL].inverseEnable = true;
84 modeInfo[MODE_SPHERE].name = i18n( "Sphere" );
85 modeInfo[MODE_SPHERE].inverseEnable = true;
87 modeInfo[MODE_EXPONENTIAL].name = i18n( "Exponential" );
88 modeInfo[MODE_EXPONENTIAL].inverseEnable = false;
90 modeInfo[MODE_CONTRACTION].name = i18n( "Contraction" );
91 modeInfo[MODE_CONTRACTION].inverseEnable = false;
93 modeInfo[MODE_WAVE].name = i18n( "Wave" );
94 modeInfo[MODE_WAVE].inverseEnable = false;
96 modeInfo[MODE_CURVATURE].name = i18n( "Curvature" );
97 modeInfo[MODE_CURVATURE].inverseEnable = true;
100 //-----------------------------------------------------------------------------
101 // KPreviewWidget
104 KPreviewWidget::KPreviewWidget( QWidget *parent ) :
105 QWidget ( parent ) { }
107 void KPreviewWidget::paintEvent( QPaintEvent *event )
109 if( saver != 0 )
110 saver->do_refresh( event->rect() );
113 void KPreviewWidget::notifySaver( KScienceSaver *s )
115 saver = s;
118 //-----------------------------------------------------------------------------
119 // Screen Saver
122 struct KScienceData
124 T32bit **offset;
125 XImage *buffer;
126 XImage *xRootWin;
127 GC gc;
130 KScienceSaver::KScienceSaver( WId id, bool s, bool gP )
131 : KScreenSaver( id )
133 d = new KScienceData;
134 d->gc = XCreateGC(qt_xdisplay(), id, 0, 0);
135 d->xRootWin = 0;
136 d->buffer = 0;
138 moveOn = true;
139 grabPixmap = gP;
140 setup = s;
142 vx = vy = 0.0;
143 readSettings();
145 if( !grabPixmap )
147 grabRootWindow();
148 initialize();
149 do_refresh( QRect ( 0, 0, width(), height() ) );
152 connect( &timer, SIGNAL( timeout() ), SLOT( slotTimeout() ) );
153 timer.start( SCI_MAX_SPEED - speed[mode] );
156 KScienceSaver::~KScienceSaver()
158 timer.stop();
159 releaseLens();
160 if ( d->xRootWin )
161 XDestroyImage( d->xRootWin );
162 XFreeGC(qt_xdisplay(), d->gc );
163 delete d;
166 void KScienceSaver::myAssert( bool term, const char *eMsg )
168 if( !term ) {
169 fprintf(stderr, "Error in KScreensaver - mode Science: %s\n", eMsg);
170 releaseLens();
171 exit(-1);
175 void KScienceSaver::initialize()
177 KRandomSequence rnd;
178 initLens();
179 signed int ws = (signed int) (width() - diam);
180 signed int hs = (signed int) (height() - diam);
182 x = (ws > 0) ? (rnd.getDouble() * ws ) : 0.0;
183 y = (hs > 0) ? (rnd.getDouble() * hs ) : 0.0;
185 xcoord = (int) x;
186 ycoord = (int) y;
188 switch( bpp ) {
189 case 1 : applyLens = &KScienceSaver::applyLens8bpp; break;
190 case 2 : applyLens = &KScienceSaver::applyLens16bpp; break;
191 case 3 : applyLens = &KScienceSaver::applyLens24bpp; break;
192 case 4 : applyLens = &KScienceSaver::applyLens32bpp; break;
193 default: myAssert( false, "unsupported colordepth "\
194 "(only 8, 16, 24, 32 bpp supported)" );
198 void KScienceSaver::initWhirlLens()
200 double dx, dy, r, phi, intens;
201 T32bit *off;
202 T32bit xo, yo;
204 intens = double( intensity[mode] + 1) / 5.0;
205 if( inverse[mode] )
206 intens = -intens;
208 for(int y = side-1; y >= 0; y--)
210 dy = y - origin;
211 off = d->offset[y] = (T32bit *) malloc(sizeof(T32bit) * side);
212 myAssert( off != 0, "too few memory" );
213 for(int x = side-1; x >= 0; x--)
215 dx = x - origin;
216 r = sqrt( dx*dx + dy*dy );
218 if( r < radius )
220 if ( dx == 0.0 )
221 phi = (dy > 0.0) ? M_PI_2 :-(M_PI_2);
222 else
223 phi = atan2( dy, dx );
224 phi += intens * ( radius - r ) / ( r+7.0 );
225 xo = (T32bit) ( origin + r*cos( phi ) - x );
226 yo = (T32bit) ( origin + r*sin( phi ) - y );
227 off[x] = xo*bpp + yo*imgnext;
229 else
230 if( hideBG[mode] )
231 off[x] = (border-y)*imgnext + (border-x)*bpp;
232 else
233 off[x] = 0;
238 void KScienceSaver::initSphereLens()
240 double dx, dy, r, xr, yr, phi, intens;
241 T32bit *off;
242 T32bit xo, yo;
244 intens = 1.0 - double( intensity[mode] ) / 20.0;
246 if( inverse[mode] )
247 intens = -intens;
249 for(int y = side-1; y >= 0; y--)
251 dy = y - origin;
252 off = d->offset[y] = (T32bit *) malloc(sizeof(T32bit) * side);
253 myAssert( off != 0, "too few memory" );
254 for(int x = side-1; x >= 0; x--)
256 dx = x - origin;
257 r = sqrt( dx*dx + dy*dy );
259 if( r < radius )
261 xr = (double) radius*cos(asin(dy/radius));
262 yr = (double) radius*cos(asin(dx/radius));
263 phi = (xr != 0.0) ? asin(dx/xr) : 0.0;
264 xo = (T32bit) (origin + intens*2.0*phi*xr / M_PI - x);
265 phi = (yr != 0.0) ? asin(dy/yr) : 0.0;
266 yo = (T32bit) (origin + intens*2.0*phi*yr / M_PI - y);
267 off[x] = xo*bpp + yo*imgnext;
269 else
270 if( hideBG[mode] )
271 off[x] = (border-y)*imgnext + (border-x)*bpp;
272 else
273 off[x] = 0;
278 void KScienceSaver::initExponentialLens()
280 double dx, dy, r, rnew, f, intens;
281 T32bit *off;
282 T32bit xo, yo;
284 if( mode == MODE_EXPONENTIAL )
285 intens = - (0.1 + 0.8 * double( intensity[mode] + 2) / 10.0);
286 else
287 intens = 0.9 - 0.8 * double( intensity[mode] ) / 10.0;
289 for(int y = side-1; y >= 0; y--)
291 dy = y - origin;
292 off = d->offset[y] = (T32bit *) malloc(sizeof(T32bit) * side);
293 myAssert( off != 0, "too few memory" );
294 for(int x = side-1; x >= 0; x--)
296 dx = x - origin;
297 r = sqrt( dx*dx + dy*dy );
299 if( r < radius )
301 if( r == 0.0 )
302 f = 0.0;
303 else
305 rnew = radius*(pow(r, intens) / pow(radius, intens));
306 f = double ((int)rnew % radius) / r;
308 xo = (T32bit) ( origin + f*dx - x );
309 yo = (T32bit) ( origin + f*dy - y );
310 off[x] = xo*bpp + yo*imgnext;
312 else
313 if( hideBG[mode] )
314 off[x] = (border-y)*imgnext + (border-x)*bpp;
315 else
316 off[x] = 0;
321 void KScienceSaver::initCurvatureLens()
323 double dx, dy, r, f, intens;
324 T32bit *off;
325 T32bit xo, yo;
327 intens = (double) radius*intensity[mode] / 20.0;
328 if( inverse[mode] ) intens = -intens;
330 for(int y = side-1; y >= 0; y--)
332 dy = y - origin;
333 off = d->offset[y] = (T32bit *) malloc(sizeof(T32bit) * side);
334 myAssert( off != 0, "too few memory" );
335 for(int x = side-1; x >= 0; x--)
337 dx = x - origin;
338 r = sqrt( dx*dx + dy*dy );
340 if( r < radius )
342 if( r == 0.0 )
343 f = 0.0;
344 else
345 f = (r - intens * sin(M_PI * r/(double)radius)) / r;
346 xo = (T32bit) ( origin + f*dx - x );
347 yo = (T32bit) ( origin + f*dy - y );
348 off[x] = xo*bpp + yo*imgnext;
350 else
351 if( hideBG[mode] )
352 off[x] = (border-y)*imgnext + (border-x)*bpp;
353 else
354 off[x] = 0;
359 void KScienceSaver::initWaveLens()
361 double dx, dy, r, rnew, f, intens, k;
362 T32bit *off;
363 T32bit xo, yo;
365 intens = (double) intensity[mode] + 1.0;
366 k = (intensity[mode] % 2) ? -12.0 : 12.0;
368 for(int y = side-1; y >= 0; y--)
370 dy = y - origin;
371 off = d->offset[y] = (T32bit *) malloc(sizeof(T32bit) * side);
372 myAssert( off != 0, "too few memory" );
373 for(int x = side-1; x >= 0; x--)
375 dx = x - origin;
376 r = sqrt( dx*dx + dy*dy );
378 if( r < radius )
380 if( r == 0.0 )
381 f = 0.0;
382 else
384 rnew = r - k * sin( M_PI * intens * r/(double)radius);
385 f = double ((int)rnew % radius) / r;
387 xo = (T32bit) ( origin + f*dx - x );
388 yo = (T32bit) ( origin + f*dy - y );
389 off[x] = xo*bpp + yo*imgnext;
391 else
392 if( hideBG[mode] )
393 off[x] = (border-y)*imgnext + (border-x)*bpp;
394 else
395 off[x] = 0;
400 void KScienceSaver::initLens()
402 int min = (width() < height()) ? width() : height();
403 border = 1 + SCI_MAX_MOVE;
405 radius = (size[mode] * min) / 100;
406 if( radius<<1 == min ) radius--;
407 diam = radius << 1;
408 myAssert( diam < min, "assertion violated: diam < min" );
409 origin = radius + border;
410 side = origin << 1;
412 d->buffer = XSubImage( d->xRootWin, 0, 0, side, side );
413 myAssert( d->buffer != 0, "can't allocate pixmap" );
415 d->offset = (T32bit **) malloc( sizeof(T32bit *) * side );
416 myAssert( d->offset != 0, "too few memory" );
418 switch( mode ) {
419 case MODE_WHIRL: initWhirlLens(); break;
420 case MODE_SPHERE: initSphereLens(); break;
421 case MODE_EXPONENTIAL:
422 case MODE_CONTRACTION: initExponentialLens(); break;
423 case MODE_CURVATURE: initCurvatureLens(); break;
424 case MODE_WAVE: initWaveLens(); break;
425 default: myAssert( false, "internal error (wrong mode in initLens() )" );
429 void KScienceSaver::releaseLens()
431 if( d->offset != 0 ) {
432 for(int i=0; i<side; i++)
433 if( d->offset[i] != 0 ) free( d->offset[i] );
434 free( d->offset );
435 d->offset = 0;
437 if( d->buffer != 0 ) {
438 XDestroyImage( d->buffer );
439 d->buffer = 0;
443 void KScienceSaver::setMode( int m )
445 timer.stop();
447 releaseLens();
448 int old = mode;
449 mode = m;
450 vx = copysign( moveX[mode], vx );
451 vy = copysign( moveY[mode], vy );
452 int dm = diam;
453 initLens();
454 if( hideBG[old] ^ hideBG[m] )
455 do_refresh( QRect( 0, 0, width(), height() ) );
456 else
457 if( diam < dm )
459 do_refresh( QRect( (int) x+diam, (int) y, dm-diam, diam ) );
460 do_refresh( QRect( (int) x, (int) y+diam, dm, dm-diam ) );
463 timer.start( SCI_MAX_SPEED - speed[mode] );
466 void KScienceSaver::setMoveX( int s )
468 timer.stop();
470 moveX[mode] = s;
471 vx = copysign( moveX[mode], vx );
473 timer.start( SCI_MAX_SPEED - speed[mode] );
476 void KScienceSaver::setMoveY( int s )
478 timer.stop();
480 moveY[mode] = s;
481 vy = copysign( moveY[mode], vy );
483 timer.start( SCI_MAX_SPEED - speed[mode] );
486 void KScienceSaver::setMove( bool s )
488 moveOn = s;
491 void KScienceSaver::setSize( int s )
493 timer.stop();
495 releaseLens();
496 int dm = diam;
497 size[mode] = s;
498 initLens();
499 if( diam < dm )
501 do_refresh( QRect( (int) x+diam, (int) y, dm-diam, diam ) );
502 do_refresh( QRect( (int) x, (int) y+diam, dm, dm-diam ) );
505 timer.start( SCI_MAX_SPEED - speed[mode] );
508 void KScienceSaver::setSpeed( int s )
510 speed[mode] = s;
512 timer.changeInterval( SCI_MAX_SPEED - speed[mode] );
515 void KScienceSaver::setIntensity( int i )
517 timer.stop();
519 releaseLens();
520 intensity[mode] = i;
521 initLens();
523 timer.start( SCI_MAX_SPEED - speed[mode]);
526 void KScienceSaver::setInverse( bool b )
528 timer.stop();
530 releaseLens();
531 inverse[mode] = b;
532 initLens();
534 timer.start( SCI_MAX_SPEED - speed[mode]);
537 void KScienceSaver::setGravity( bool b )
539 timer.stop();
541 releaseLens();
542 gravity[mode] = b;
543 vy = copysign( moveY[mode], vy );
544 initLens();
546 timer.start( SCI_MAX_SPEED - speed[mode]);
549 void KScienceSaver::setHideBG( bool b )
551 timer.stop();
553 releaseLens();
554 hideBG[mode] = b;
555 initLens();
556 do_refresh( QRect( 0, 0, width(), height() ) );
558 timer.start( SCI_MAX_SPEED - speed[mode]);
561 void KScienceSaver::readSettings()
563 KConfig *config = KGlobal::config();
564 QString sMode;
566 config->setGroup( "Settings" );
567 mode = config->readNumEntry( "ModeNr", SCI_DEFAULT_MODE );
569 for(int i=0; i < MAX_MODES; i++)
571 sMode.setNum( i );
572 config->setGroup( "Mode" + sMode );
573 moveX[i] = config->readNumEntry( "MoveX", SCI_DEFAULT_MOVEX);
574 moveY[i] = config->readNumEntry( "MoveY", SCI_DEFAULT_MOVEY);
575 size[i] = config->readNumEntry( "Size", SCI_DEFAULT_SIZE);
576 speed[i] = config->readNumEntry( "Speed", SCI_DEFAULT_SPEED);
577 intensity[i] = config->readNumEntry( "Intensity", SCI_DEFAULT_INTENSITY);
578 inverse[i] = config->readBoolEntry( "Inverse", SCI_DEFAULT_INVERSE);
579 gravity[i] = config->readBoolEntry( "Gravity", SCI_DEFAULT_GRAVITY);
580 hideBG[i] = config->readBoolEntry( "HideBG", SCI_DEFAULT_HIDE);
583 vx = copysign( moveX[mode], vx );
584 vy = copysign( moveY[mode], vy );
587 void KScienceSaver::do_refresh( const QRect & rect )
589 if( grabPixmap )
590 return;
591 rect.normalize();
593 if( hideBG[mode] )
595 XSetWindowBackground( qt_xdisplay(), winId(), black.pixel() );
596 XClearArea( qt_xdisplay(), winId(), rect.left(), rect.top(),
597 rect.width(), rect.height(), false );
599 else
601 myAssert( d->xRootWin != 0, "root window not grabbed" );
602 XPutImage( qt_xdisplay(), winId(), d->gc, d->xRootWin,
603 rect.left(), rect.top(),
604 rect.left(), rect.top(),
605 rect.width(), rect.height() );
609 void KScienceSaver::slotTimeout()
611 if( grabPixmap ) {
612 if( !QWidget::find(winId())->isActiveWindow() )
613 return;
614 grabPreviewWidget();
615 grabPixmap = false;
616 initialize();
617 if( hideBG[mode] )
618 do_refresh( QRect ( 0, 0, width(), height() ) );
621 signed int oldx = xcoord, oldy = ycoord;
623 if( gravity[mode] ) {
624 double h = double(y+1.0) / double(height()-diam);
625 if( h > 1.0 ) h = 1.0;
626 vy = sqrt( h ) * ( (vy > 0.0) ? moveY[mode] : -moveY[mode] );
628 myAssert( abs((int)rint(vy)) <= border, "assertion violated: vy <= border" );
630 if( moveOn )
632 x += vx;
633 y += vy;
636 if( x <= 0.0 ) {
637 vx = -vx;
638 x = 0.0;
640 if( int(x) + diam >= width()) {
641 vx = -vx;
642 myAssert( width()-diam > 0, "assertion violated: width-diam > 0" );
643 x = (double) (width() - diam - 1);
645 if( y <= 0.0 ) {
646 vy = -vy;
647 y = 0.0;
649 if( int(y) + diam >= height() ) {
650 vy = -vy;
651 myAssert( height() - diam > 0, "assertion violated: height-diam > 0" );
652 y = (double) (height() - diam - 1);
655 xcoord = (int) x ;
656 ycoord = (int) y ;
657 signed int dx = (signed int) xcoord - oldx;
658 signed int dy = (signed int) ycoord - oldy;
659 signed int xs, ys, xd, yd, w, h;
661 if( dx > 0 ) {
662 w = diam+dx;
663 xd = oldx;
664 xs = border-dx;
665 if( dy > 0 ) {
666 h = diam+dy;
667 yd = oldy;
668 ys = border-dy;
670 else {
671 h = diam-dy;
672 yd = ycoord;
673 ys = border;
676 else {
677 w = diam-dx;
678 xd = xcoord;
679 xs = border;
680 if( dy > 0 ) {
681 h = diam+dy;
682 yd = oldy;
683 ys = border-dy;
684 } else {
685 h = diam-dy;
686 yd = ycoord;
687 ys = border;
691 if( xd + w >= width() ) w = width() - xd - 1;
692 if( yd + h >= height() ) h = height() - yd - 1;
694 //printf("%d: (dx: %3d, dy: %3d), diam: %3d, (xc: %3d, yc: %3d), (xs: %3d, ys: %3d), (xd: %3d, yd: %3d), (w: %3d, h: %3d)\n", mode, dx, dy, diam, xcoord, ycoord, xs, ys, xd, yd, w, h);
695 myAssert( dx <= border && dy <=border, "assertion violated: dx or dy <= border");
696 myAssert( xcoord >= 0 && ycoord >= 0, "assertion violated: xcoord, ycoord >= 0 ");
697 myAssert( xd+w < width(), "assertion violated: xd+w < width" );
698 myAssert( yd+h < height(), "assertion violated: yd+h < height" );
700 if( hideBG[mode] )
701 blackPixel( xcoord, ycoord );
702 (this->*applyLens)(xs, ys, xd, yd, w, h);
703 XPutImage( qt_xdisplay(), winId(), d->gc, d->buffer, 0, 0, xd, yd, w, h );
704 if( hideBG[mode] )
705 blackPixelUndo( xcoord, ycoord );
708 void KScienceSaver::grabRootWindow()
710 Display *dsp = qt_xdisplay();
711 Window rootwin = RootWindow( dsp, qt_xscreen() );
713 // grab contents of root window
714 if( d->xRootWin )
715 XDestroyImage( d->xRootWin );
717 d->xRootWin = XGetImage( dsp, rootwin, 0, 0, width(),
718 height(), AllPlanes, ZPixmap);
719 myAssert( d->xRootWin, "unable to grab root window\n" );
721 imgnext = d->xRootWin->bytes_per_line;
722 bpp = ( d->xRootWin->bits_per_pixel ) >> 3;
725 void KScienceSaver::grabPreviewWidget()
727 myAssert( QWidget::find(winId())->isActiveWindow(), "can't grab preview widget: dialog not active()" );
729 if( d->xRootWin )
730 XDestroyImage( d->xRootWin );
732 Display *dsp = qt_xdisplay();
733 d->xRootWin = XGetImage( dsp, winId(), 0, 0, width(), height(), AllPlanes, ZPixmap);
734 myAssert( d->xRootWin, "unable to grab preview window\n" );
736 imgnext = d->xRootWin->bytes_per_line;
737 bpp = ( d->xRootWin->bits_per_pixel ) >> 3;
740 void KScienceSaver::blackPixel( int x, int y )
742 unsigned char black = (char) BlackPixel( qt_xdisplay(), qt_xscreen() );
743 unsigned int adr = x*bpp + y*imgnext;
745 for(int i=0; i<bpp; i++) {
746 blackRestore[i] = d->xRootWin->data[adr];
747 d->xRootWin->data[adr++] = black;
751 void KScienceSaver::blackPixelUndo( int x, int y )
753 unsigned int adr = x*bpp + y*imgnext;
754 for(int i=0; i<bpp; i++)
755 d->xRootWin->data[adr++] = blackRestore[i];
758 // hm....
760 void KScienceSaver::applyLens8bpp(int xs, int ys, int xd, int yd, int w, int h)
762 T32bit *off;
763 char *img1, *img2, *data;
764 signed int ix, iy, datanext = d->buffer->bytes_per_line - w;
766 img1 = d->xRootWin->data + xd + yd*imgnext;
767 data = d->buffer->data;
768 for(iy = ys; iy < ys+h; iy++)
770 off = d->offset[iy] + xs;
771 img2 = img1;
772 for(ix = w; ix > 0; ix--)
773 *data++ = img2++[*off++];
774 img1 += imgnext;
775 data += datanext;
780 void KScienceSaver::applyLens16bpp(int xs, int ys, int xd, int yd, int w, int h)
782 T32bit *off;
783 char *img1, *img2, *data;
784 int ix, iy, datanext = d->buffer->bytes_per_line - (w << 1);
786 img1 = d->xRootWin->data + (xd << 1) + yd*imgnext;
787 data = d->buffer->data;
788 for(iy = ys; iy < ys+h; iy++)
790 off = d->offset[iy] + xs;
791 img2 = img1;
792 for(ix = w; ix > 0; ix--) {
793 *data++ = img2++[*off];
794 *data++ = img2++[*off++];
796 img1 += imgnext;
797 data += datanext;
801 void KScienceSaver::applyLens24bpp(int xs, int ys, int xd, int yd, int w, int h)
803 T32bit *off;
804 char *img1, *img2, *data;
805 signed int ix, iy, datanext = d->buffer->bytes_per_line - 3*w;
807 img1 = d->xRootWin->data + 3*xd + yd*imgnext;
808 data = d->buffer->data;
809 for(iy = ys; iy < ys+h; iy++)
811 off = d->offset[iy] + xs;
812 img2 = img1;
813 for(ix = w; ix > 0; ix--) {
814 *data++ = img2++[*off];
815 *data++ = img2++[*off];
816 *data++ = img2++[*off++];
818 img1 += imgnext;
819 data += datanext;
823 void KScienceSaver::applyLens32bpp(int xs, int ys, int xd, int yd, int w, int h)
825 T32bit *off;
826 char *img1, *img2, *data;
827 signed int ix, iy, datanext = d->buffer->bytes_per_line - (w << 2);
829 img1 = d->xRootWin->data + (xd << 2) + yd*imgnext;
830 data = d->buffer->data;
831 for(iy = ys; iy < ys+h; iy++)
833 off = d->offset[iy] + xs;
834 img2 = img1;
835 for(ix = w; ix > 0; ix--) {
836 *data++ = img2++[*off];
837 *data++ = img2++[*off];
838 *data++ = img2++[*off];
839 *data++ = img2++[*off++];
841 img1 += imgnext;
842 data += datanext;
847 //-----------------------------------------------------------------------------
849 KScienceSetup::KScienceSetup( QWidget *parent, const char *name )
850 : KDialogBase( parent, name, true, i18n( "Setup Science Screen Saver" ),
851 Ok|Cancel|Help, Ok, true ), saver( 0 )
853 readSettings();
854 initModeInfo();
856 QWidget *main = makeMainWidget();
858 QHBoxLayout *lt = new QHBoxLayout( main, 0, spacingHint());
859 QVBoxLayout *ltm = new QVBoxLayout;
860 lt->addLayout( ltm );
861 QVBoxLayout *ltc = new QVBoxLayout;
862 lt->addLayout( ltc );
864 // mode
865 QLabel *label = new QLabel( i18n("Mode:"), main );
866 ltm->addWidget( label );
868 QListBox *c = new QListBox( main );
869 for(int i = 0; i<MAX_MODES; i++)
870 c->insertItem( modeInfo[i].name );
871 c->setCurrentItem( mode );
872 c->setFixedHeight( 5 * c->fontMetrics().height() );
873 connect( c, SIGNAL( highlighted( int ) ), SLOT( slotMode( int ) ) );
874 ltm->addWidget( c );
876 // inverse
877 QCheckBox *cbox = checkInverse = new QCheckBox( i18n("Inverse"), main );
878 cbox->setEnabled( modeInfo[mode].inverseEnable );
879 cbox->setChecked( inverse[mode] );
880 connect( cbox, SIGNAL( clicked() ), SLOT( slotInverse() ) );
881 ltm->addWidget( cbox );
883 // gravity
884 cbox = checkGravity = new QCheckBox( i18n("Gravity"), main );
885 cbox->setChecked( gravity[mode] );
886 connect( cbox, SIGNAL( clicked() ), SLOT( slotGravity() ) );
887 ltm->addWidget( cbox );
889 // hide background
890 cbox = checkHideBG = new QCheckBox( i18n("Hide background"), main );
891 cbox->setChecked( hideBG[mode] );
892 connect( cbox, SIGNAL( clicked() ), SLOT( slotHideBG() ) );
893 ltm->addWidget( cbox );
894 ltm->addStretch();
896 // size
897 label = new QLabel( i18n("Size:"), main );
898 ltc->addWidget( label );
900 slideSize = new QSlider(9, 50, 5, size[mode], QSlider::Horizontal,
901 main );
902 slideSize->setMinimumSize( 90, 20 );
903 slideSize->setTickmarks(QSlider::Below);
904 slideSize->setTickInterval(5);
905 connect( slideSize, SIGNAL( sliderMoved( int ) ),
906 SLOT( slotSize( int ) ) );
907 connect( slideSize, SIGNAL( sliderPressed() ),
908 SLOT( slotSliderPressed() ) );
909 connect( slideSize, SIGNAL( sliderReleased() ),
910 SLOT( slotSliderReleased() ) );
912 ltc->addWidget( slideSize );
914 // intensity
915 label = new QLabel( i18n("Intensity:"), main );
916 ltc->addWidget( label );
918 slideIntensity = new QSlider(0, 10, 1, intensity[mode],
919 QSlider::Horizontal, main );
920 slideIntensity->setMinimumSize( 90, 20 );
921 slideIntensity->setTickmarks(QSlider::Below);
922 slideIntensity->setTickInterval(1);
923 connect( slideIntensity, SIGNAL( sliderMoved( int ) ),
924 SLOT( slotIntensity( int )) );
925 connect( slideIntensity, SIGNAL( sliderPressed() ),
926 SLOT( slotSliderPressed() ) );
927 connect( slideIntensity, SIGNAL( sliderReleased() ),
928 SLOT( slotSliderReleased() ) );
929 ltc->addWidget( slideIntensity );
931 // speed
932 label = new QLabel( i18n("Speed:"), main );
933 ltc->addWidget( label );
935 slideSpeed = new QSlider(0, SCI_MAX_SPEED, 10, speed[mode],
936 QSlider::Horizontal, main );
937 slideSpeed->setMinimumSize( 90, 20 );
938 slideSpeed->setTickmarks(QSlider::Below);
939 slideSpeed->setTickInterval(10);
940 connect( slideSpeed, SIGNAL( sliderMoved( int ) ),
941 SLOT( slotSpeed( int ) ) );
942 ltc->addWidget( slideSpeed );
944 // motion
945 label = new QLabel( i18n("Motion:"), main );
946 ltc->addWidget( label );
948 QHBoxLayout *ltcm = new QHBoxLayout;
949 ltc->addLayout( ltcm );
951 slideMoveX = new QSlider(0, SCI_MAX_MOVE, 5, moveX[mode],
952 QSlider::Horizontal, main );
953 slideMoveX->setMinimumSize( 40, 20 );
954 slideMoveX->setTickmarks(QSlider::Below);
955 slideMoveX->setTickInterval(5);
956 connect( slideMoveX, SIGNAL( sliderMoved( int ) ),
957 SLOT( slotMoveX( int ) ) );
958 ltcm->addWidget( slideMoveX );
960 slideMoveY = new QSlider(0, SCI_MAX_MOVE, 5, moveY[mode],
961 QSlider::Horizontal, main );
962 slideMoveY->setMinimumSize( 40, 20 );
963 slideMoveY->setTickmarks(QSlider::Below);
964 slideMoveY->setTickInterval(5);
965 connect( slideMoveY, SIGNAL( sliderMoved( int ) ),
966 SLOT( slotMoveY( int ) ) );
967 ltcm->addWidget( slideMoveY );
969 ltc->addStretch();
971 // preview
972 preview = new KPreviewWidget( main );
973 preview->setFixedSize( 220, 170 );
974 QPixmap p( locate("data", "kscreensaver/pics/kscience.png") );
975 if( p.isNull() )
976 preview->setBackgroundColor( black );
977 else
978 preview->setBackgroundPixmap( p );
979 preview->show(); // otherwise saver does not get correct size
980 lt->addWidget( preview );
982 // let the preview window display before creating the saver
983 kapp->processEvents();
985 saver = new KScienceSaver( preview->winId(), true, !p.isNull() );
986 preview->notifySaver( saver );
989 KScienceSetup::~KScienceSetup()
991 delete saver; // be sure to delete this first
994 void KScienceSetup::updateSettings()
996 // update dialog
997 slideMoveX ->setValue( moveX[mode] );
998 slideMoveY ->setValue( moveY[mode] );
999 slideSize ->setValue( size[mode] );
1000 slideSpeed ->setValue( speed[mode] );
1001 slideIntensity->setValue( intensity[mode] );
1002 checkInverse ->setEnabled( modeInfo[mode].inverseEnable );
1003 checkInverse ->setChecked( inverse[mode] );
1004 checkGravity ->setChecked( gravity[mode] );
1005 checkHideBG ->setChecked( hideBG[mode] );
1008 // read settings from config file
1009 void KScienceSetup::readSettings()
1011 KConfig *config = KGlobal::config();
1012 QString sMode;
1014 config->setGroup( "Settings" );
1015 mode = config->readNumEntry( "ModeNr", SCI_DEFAULT_MODE );
1017 for(int i=0; i < MAX_MODES; i++)
1019 sMode.setNum( i );
1020 config->setGroup( "Mode" + sMode );
1021 moveX[i] = config->readNumEntry( "MoveX", SCI_DEFAULT_MOVEX);
1022 moveY[i] = config->readNumEntry( "MoveY", SCI_DEFAULT_MOVEY);
1023 size[i] = config->readNumEntry( "Size", SCI_DEFAULT_SIZE);
1024 speed[i] = config->readNumEntry( "Speed", SCI_DEFAULT_SPEED);
1025 intensity[i] = config->readNumEntry( "Intensity", SCI_DEFAULT_INTENSITY);
1026 inverse[i] = config->readBoolEntry( "Inverse", SCI_DEFAULT_INVERSE);
1027 gravity[i] = config->readBoolEntry( "Gravity", SCI_DEFAULT_GRAVITY);
1028 hideBG[i] = config->readBoolEntry( "HideBG", SCI_DEFAULT_HIDE);
1032 void KScienceSetup::slotMode( int m )
1034 mode = m;
1036 if( saver )
1037 saver->setMode( mode );
1039 updateSettings();
1042 void KScienceSetup::slotInverse( )
1044 inverse[mode] = checkInverse->isChecked();
1046 if( saver )
1047 saver->setInverse( inverse[mode] );
1050 void KScienceSetup::slotGravity( )
1052 gravity[mode] = checkGravity->isChecked();
1054 if( saver )
1055 saver->setGravity( gravity[mode] );
1058 void KScienceSetup::slotHideBG( )
1060 hideBG[mode] = checkHideBG->isChecked();
1062 if( saver )
1063 saver->setHideBG( hideBG[mode] );
1066 void KScienceSetup::slotMoveX( int x )
1068 moveX[mode] = x;
1070 if( saver )
1071 saver->setMoveX( x );
1074 void KScienceSetup::slotMoveY( int y )
1076 moveY[mode] = y;
1078 if( saver )
1079 saver->setMoveY( y );
1082 void KScienceSetup::slotSize( int s )
1084 size[mode] = s;
1086 if( saver )
1087 saver->setSize( s );
1090 void KScienceSetup::slotSpeed( int s )
1092 speed[mode] = s;
1094 if( saver )
1095 saver->setSpeed( s );
1098 void KScienceSetup::slotIntensity( int i )
1100 intensity[mode] = i;
1102 if( saver )
1103 saver->setIntensity( i );
1106 void KScienceSetup::slotSliderPressed()
1108 if( saver )
1109 saver->setMove( false );
1112 void KScienceSetup::slotSliderReleased()
1114 if( saver )
1115 saver->setMove( true );
1118 // Ok pressed - save settings and exit
1119 void KScienceSetup::slotOk()
1121 KConfig *config = KGlobal::config();
1122 QString sSize, sSpeed, sIntensity, sMode;
1124 config->setGroup( "Settings" );
1125 config->writeEntry( "ModeNr", mode );
1127 for(int i=0; i<MAX_MODES; i++)
1129 sMode.setNum( i );
1130 config->setGroup( "Mode" + sMode );
1131 config->writeEntry( "MoveX", moveX[i] );
1132 config->writeEntry( "MoveY", moveY[i] );
1133 config->writeEntry( "Size", size[i] );
1134 config->writeEntry( "Speed", speed[i] );
1135 config->writeEntry( "Intensity", intensity[i] );
1136 config->writeEntry( "Inverse", inverse[i] );
1137 config->writeEntry( "Gravity", gravity[i] );
1138 config->writeEntry( "HideBG", hideBG[i] );
1141 config->sync();
1143 accept();
1146 void KScienceSetup::slotHelp()
1148 QString about = i18n("Science Version 0.26.5\n\nWritten by Rene Beutler (1998)\nrbeutler@g26.ethz.ch");
1149 KMessageBox::about(this,
1150 about);