Edit

IABSD.fr/xenocara/app/xlockmore/modes/laser.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2006-11-26 11:07:42
    Hash : 110b2a92
    Message : Importing xlockmore 5.22

  • app/xlockmore/modes/laser.c
  • /* -*- Mode: C; tab-width: 4 -*- */
    /* laser --- spinning lasers */
    
    #if !defined( lint ) && !defined( SABER )
    static const char sccsid[] = "@(#)laser.c	5.00 2000/11/01 xlockmore";
    
    #endif
    
    /*-
     * Copyright (c) 1995 Pascal Pensa <pensa@aurora.unice.fr>
     *
     * Permission to use, copy, modify, and distribute this software and its
     * documentation for any purpose and without fee is hereby granted,
     * provided that the above copyright notice appear in all copies and that
     * both that copyright notice and this permission notice appear in
     * supporting documentation.
     *
     * This file is provided AS IS with no warranties of any kind.  The author
     * shall have no liability with respect to the infringement of copyrights,
     * trade secrets or any patents by this file or any part thereof.  In no
     * event will the author be liable for any lost revenue or profits or
     * other special, indirect and consequential damages.
     *
     * Revision History:
     * 01-Nov-2000: Allocation checks
     * 10-May-1997: Compatible with xscreensaver
     * 1995: Written.
     */
    
    #ifdef STANDALONE
    #define MODE_laser
    #define PROGCLASS "Laser"
    #define HACK_INIT init_laser
    #define HACK_DRAW draw_laser
    #define laser_opts xlockmore_opts
    #define DEFAULTS "*delay: 20000 \n" \
     "*count: -10 \n" \
     "*cycles: 200 \n" \
     "*ncolors: 200 \n"
    #define BRIGHT_COLORS
    #include "xlockmore.h"		/* in xscreensaver distribution */
    #else /* STANDALONE */
    #include "xlock.h"		/* in xlockmore distribution */
    #endif /* STANDALONE */
    
    #ifdef MODE_laser
    
    ModeSpecOpt laser_opts =
    {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
    
    #ifdef USE_MODULES
    ModStruct   laser_description =
    {"laser", "init_laser", "draw_laser", "release_laser",
     "refresh_laser", "init_laser", (char *) NULL, &laser_opts,
     20000, -10, 200, 1, 64, 1.0, "",
     "Shows spinning lasers", 0, NULL};
    
    #endif
    
    #define MINREDRAW 3		/* Number of redrawn on each frame */
    #define MAXREDRAW 8
    
    #define MINLASER  1		/* Laser number */
    
    #define MINWIDTH  2		/* Laser ray width range */
    #define MAXWIDTH 40
    
    #define MINSPEED  2		/* Speed range */
    #define MAXSPEED 17
    
    #define MINDIST  10		/* Minimal distance from edges */
    
    #define COLORSTEP 2		/* Laser color step */
    
    #define RANGE_RAND(min,max) (int) ((min) + LRAND() % ((max) - (min)))
    
    typedef enum {
    	TOP, RIGHT, BOTTOM, LEFT
    } border;
    
    typedef struct {
    	int         bx;		/* border x */
    	int         by;		/* border y */
    	border      bn;		/* active border */
    	int         dir;	/* direction */
    	int         speed;	/* laser velocity from MINSPEED to MAXSPEED */
    	int         sx[MAXWIDTH];	/* x stack */
    	int         sy[MAXWIDTH];	/* x stack */
    	XGCValues   gcv;	/* for color */
    } laserstruct;
    
    typedef struct {
    	int         width;
    	int         height;
    	int         cx;		/* center x */
    	int         cy;		/* center y */
    	int         lw;		/* laser width */
    	int         ln;		/* laser number */
    	int         lr;		/* laser redraw */
    	int         sw;		/* stack width */
    	int         so;		/* stack offset */
    	int         time;	/* up time */
    	GC          stippledGC;
    	XGCValues   gcv_black;	/* for black color */
    	laserstruct *laser;
    } lasersstruct;
    
    static lasersstruct *lasers = (lasersstruct *) NULL;
    
    static void
    free_laser(Display *display, lasersstruct *lp)
    {
    	if (lp->laser != NULL) {
    		free(lp->laser);
    		lp->laser = (laserstruct *) NULL;
    	}
    	if (lp->stippledGC != None) {
    		XFreeGC(display, lp->stippledGC);
    		lp->stippledGC = None;
    	}
    }
    
    void
    init_laser(ModeInfo * mi)
    {
    	Display *display = MI_DISPLAY(mi);
    	int         i, c = 0;
    	lasersstruct *lp;
    
    	if (lasers == NULL) {
    		if ((lasers = (lasersstruct *) calloc(MI_NUM_SCREENS(mi),
    					     sizeof (lasersstruct))) == NULL)
    			return;
    	}
    	lp = &lasers[MI_SCREEN(mi)];
    
    	lp->width = MI_WIDTH(mi);
    	lp->height = MI_HEIGHT(mi);
    	lp->time = 0;
    
    	lp->ln = MI_COUNT(mi);
    	if (lp->ln < -MINLASER) {
    		/* if lp->ln is random ... the size can change */
    		if (lp->laser != NULL) {
    			free(lp->laser);
    			lp->laser = (laserstruct *) NULL;
    		}
    		lp->ln = NRAND(-lp->ln - MINLASER + 1) + MINLASER;
    	} else if (lp->ln < MINLASER)
    		lp->ln = MINLASER;
    
    	if (lp->laser == NULL) {
    		if ((lp->laser = (laserstruct *) malloc(lp->ln *
    				sizeof (laserstruct))) == NULL) {
    			free_laser(display, lp);
    			return;
    		}
    	}
    	if (lp->stippledGC == None) {
    		XGCValues   gcv;
    
    		gcv.foreground = MI_WHITE_PIXEL(mi);
    		gcv.background = MI_BLACK_PIXEL(mi);
    		lp->gcv_black.foreground = MI_BLACK_PIXEL(mi);
    		if ((lp->stippledGC = XCreateGC(display, MI_WINDOW(mi),
    				GCForeground | GCBackground, &gcv)) == None) {
    			free_laser(display, lp);
    			return;
    		}
    	}
    	MI_CLEARWINDOWCOLORMAPFAST(mi, MI_GC(mi), MI_BLACK_PIXEL(mi));
    
    	if (MINDIST < lp->width - MINDIST)
    		lp->cx = RANGE_RAND(MINDIST, lp->width - MINDIST);
    	else
    		lp->cx = RANGE_RAND(0, lp->width);
    	if (MINDIST < lp->height - MINDIST)
    		lp->cy = RANGE_RAND(MINDIST, lp->height - MINDIST);
    	else
    		lp->cy = RANGE_RAND(0, lp->height);
    	lp->lw = RANGE_RAND(MINWIDTH, MAXWIDTH);
    	lp->lr = RANGE_RAND(MINREDRAW, MAXREDRAW);
    	lp->sw = 0;
    	lp->so = 0;
    
    	if (MI_NPIXELS(mi) > 2)
    		c = NRAND(MI_NPIXELS(mi));
    
    	for (i = 0; i < lp->ln; i++) {
    		laserstruct *l = &lp->laser[i];
    
    		l->bn = (border) NRAND(4);
    
    		switch (l->bn) {
    			case TOP:
    				l->bx = NRAND(lp->width);
    				l->by = 0;
    				break;
    			case RIGHT:
    				l->bx = lp->width;
    				l->by = NRAND(lp->height);
    				break;
    			case BOTTOM:
    				l->bx = NRAND(lp->width);
    				l->by = lp->height;
    				break;
    			case LEFT:
    				l->bx = 0;
    				l->by = NRAND(lp->height);
    		}
    
    		l->dir = (int) (LRAND() & 1);
    		l->speed = ((RANGE_RAND(MINSPEED, MAXSPEED) * lp->width) / 1000) + 1;
    		if (MI_NPIXELS(mi) > 2) {
    			l->gcv.foreground = MI_PIXEL(mi, c);
    			c = (c + COLORSTEP) % MI_NPIXELS(mi);
    		} else
    			l->gcv.foreground = MI_WHITE_PIXEL(mi);
    	}
    }
    
    static void
    draw_laser_once(ModeInfo * mi)
    {
    	Display    *display = MI_DISPLAY(mi);
    	lasersstruct *lp = &lasers[MI_SCREEN(mi)];
    	int         i;
    
    	for (i = 0; i < lp->ln; i++) {
    		laserstruct *l = &lp->laser[i];
    
    		if (lp->sw >= lp->lw) {
    			XChangeGC(display, lp->stippledGC, GCForeground, &(lp->gcv_black));
    			XDrawLine(display, MI_WINDOW(mi), lp->stippledGC,
    				  lp->cx, lp->cy,
    				  l->sx[lp->so], l->sy[lp->so]);
    		}
    		if (l->dir) {
    			switch (l->bn) {
    				case TOP:
    					l->bx -= l->speed;
    					if (l->bx < 0) {
    						l->by = -l->bx;
    						l->bx = 0;
    						l->bn = LEFT;
    					}
    					break;
    				case RIGHT:
    					l->by -= l->speed;
    					if (l->by < 0) {
    						l->bx = lp->width + l->by;
    						l->by = 0;
    						l->bn = TOP;
    					}
    					break;
    				case BOTTOM:
    					l->bx += l->speed;
    					if (l->bx >= lp->width) {
    						l->by = lp->height - l->bx % lp->width;
    						l->bx = lp->width;
    						l->bn = RIGHT;
    					}
    					break;
    				case LEFT:
    					l->by += l->speed;
    					if (l->by >= lp->height) {
    						l->bx = l->by % lp->height;
    						l->by = lp->height;
    						l->bn = BOTTOM;
    					}
    			}
    		} else {
    			switch (l->bn) {
    				case TOP:
    					l->bx += l->speed;
    					if (l->bx >= lp->width) {
    						l->by = l->bx % lp->width;
    						l->bx = lp->width;
    						l->bn = RIGHT;
    					}
    					break;
    				case RIGHT:
    					l->by += l->speed;
    					if (l->by >= lp->height) {
    						l->bx = lp->width - l->by % lp->height;
    						l->by = lp->height;
    						l->bn = BOTTOM;
    					}
    					break;
    				case BOTTOM:
    					l->bx -= l->speed;
    					if (l->bx < 0) {
    						l->by = lp->height + l->bx;
    						l->bx = 0;
    						l->bn = LEFT;
    					}
    					break;
    				case LEFT:
    					l->by -= l->speed;
    					if (l->by < 0) {
    						l->bx = -l->bx;
    						l->by = 0;
    						l->bn = TOP;
    					}
    			}
    		}
    
    		XChangeGC(display, lp->stippledGC, GCForeground, &l->gcv);
    		XDrawLine(display, MI_WINDOW(mi), lp->stippledGC,
    			  lp->cx, lp->cy, l->bx, l->by);
    
    		l->sx[lp->so] = l->bx;
    		l->sy[lp->so] = l->by;
    
    	}
    
    	if (lp->sw < lp->lw)
    		++lp->sw;
    
    	lp->so = (lp->so + 1) % lp->lw;
    }
    
    void
    draw_laser(ModeInfo * mi)
    {
    	int         i;
    	lasersstruct *lp;
    
    	if (lasers == NULL)
    		return;
    	lp = &lasers[MI_SCREEN(mi)];
    	if (lp->laser == NULL)
    		return;
    
    	MI_IS_DRAWN(mi) = True;
    	for (i = 0; i < lp->lr; i++)
    		draw_laser_once(mi);
    
    	if (++lp->time > MI_CYCLES(mi))
    		init_laser(mi);
    }
    
    void
    release_laser(ModeInfo * mi)
    {
    	if (lasers != NULL) {
    		int         screen;
    
    		for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
    			free_laser(MI_DISPLAY(mi), &lasers[screen]);
    		free(lasers);
    		lasers = (lasersstruct *) NULL;
    	}
    }
    
    void
    refresh_laser(ModeInfo * mi)
    {
    	MI_CLEARWINDOW(mi);
    }
    
    #endif /* MODE_laser */