Edit

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

Branch :

  • Show log

    Commit

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

  • app/xlockmore/modes/mountain.c
  • /* -*- Mode: C; tab-width: 4 -*- */
    /* mountain -- square grid mountains */
    
    #if !defined( lint ) && !defined( SABER )
    static const char sccsid[] = "@(#)mountain.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_mountain
    #define PROGCLASS "Mountain"
    #define HACK_INIT init_mountain
    #define HACK_DRAW draw_mountain
    #define mountain_opts xlockmore_opts
    #define DEFAULTS "*delay: 1000 \n" \
     "*count: 30 \n" \
     "*cycles: 4000 \n" \
     "*ncolors: 64 \n" \
     "*wireframe: False \n" \
     "*fullrandom: False \n"
    #define SMOOTH_COLORS
    #include "xlockmore.h"		/* in xscreensaver distribution */
    #else /* STANDALONE */
    #include "xlock.h"		/* in xlockmore distribution */
    #endif /* STANDALONE */
    
    #ifdef MODE_mountain
    
    ModeSpecOpt mountain_opts =
    {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
    
    #ifdef USE_MODULES
    ModStruct   mountain_description =
    {"mountain", "init_mountain", "draw_mountain", "release_mountain",
     "refresh_mountain", "init_mountain", (char *) NULL, &mountain_opts,
     1000, 30, 4000, 1, 64, 1.0, "",
     "Shows Papo's mountain range", 0, NULL};
    
    #endif
    
    /* ~ 5000 Max mountain height (1000 - 10000) */
    #define MAXHEIGHT  (3 * (mp->width + mp->height))
    
    #define WORLDWIDTH 50		/* World size x * y */
    
    #define RANGE_RAND(min,max) ((min) + NRAND((max) - (min)))
    
    typedef struct {
    	int         pixelmode;
    	int         width;
    	int         height;
    	int         x, y;
    	int         offset;
    	int         stage;
    	int         h[WORLDWIDTH][WORLDWIDTH];
    	long        time;	/* up time */
    	Bool        wireframe;
    	Bool        joke;
    	GC          stippledGC;
    } mountainstruct;
    
    static mountainstruct *mountains = (mountainstruct *) NULL;
    
    static void
    spread(int  (*m)[50], int x, int y)
    {
    	int         x2, y2;
    	int         h = m[x][y];
    
    	for (y2 = y - 1; y2 <= y + 1; y2++)
    		for (x2 = x - 1; x2 <= x + 1; x2++)
    			if (x2 >= 0 && y2 >= 0 && x2 < WORLDWIDTH && y2 < WORLDWIDTH)
    				m[x2][y2] = (m[x2][y2] + h) / 2;
    }
    
    static void
    drawamountain(ModeInfo * mi)
    {
    	Display    *display = MI_DISPLAY(mi);
    	Window      window = MI_WINDOW(mi);
    	GC          gc = MI_GC(mi);
    	mountainstruct *mp = &mountains[MI_SCREEN(mi)];
    	int         x2, y2, x3, y3, y4, y5, c = 0;
    	XPoint      p[5];
    
    	if (MI_NPIXELS(mi) > 2) {
    		c = (mp->h[mp->x][mp->y] + mp->h[mp->x + 1][mp->y] +
    		  mp->h[mp->x][mp->y + 1] + mp->h[mp->x + 1][mp->y + 1]) / 4;
    		c = (c / 10 + mp->offset) % MI_NPIXELS(mi);
    	}
    	x2 = mp->x * (2 * mp->width) / (3 * WORLDWIDTH);
    	y2 = mp->y * (2 * mp->height) / (3 * WORLDWIDTH);
    	p[0].x = (x2 - y2 / 2) + (mp->width / 4);
    	p[0].y = (y2 - mp->h[mp->x][mp->y]) + mp->height / 4;
    
    	x3 = (mp->x + 1) * (2 * mp->width) / (3 * WORLDWIDTH);
    	y3 = mp->y * (2 * mp->height) / (3 * WORLDWIDTH);
    	p[1].x = (x3 - y3 / 2) + (mp->width / 4);
    	p[1].y = (y3 - mp->h[mp->x + 1][mp->y]) + mp->height / 4;
    
    	y4 = (mp->y + 1) * (2 * mp->height) / (3 * WORLDWIDTH);
    	p[2].x = (x3 - y4 / 2) + (mp->width / 4);
    	p[2].y = (y4 - mp->h[mp->x + 1][mp->y + 1]) + mp->height / 4;
    
    	y5 = (mp->y + 1) * (2 * mp->height) / (3 * WORLDWIDTH);
    	p[3].x = (x2 - y5 / 2) + (mp->width / 4);
    	p[3].y = (y5 - mp->h[mp->x][mp->y + 1]) + mp->height / 4;
    
    	p[4].x = p[0].x;
    	p[4].y = p[0].y;
    
    	if (MI_NPIXELS(mi) > 2)
    		XSetForeground(display, gc, MI_PIXEL(mi, c));
    	else
    		XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
    
    	if (mp->joke) {
    		if ((Bool) (LRAND() & 1))
    			XDrawLines(display, window, gc, p, 5, CoordModeOrigin);
    		else {
    			XFillPolygon(display, window, gc, p, 4, Complex, CoordModeOrigin);
    			if (!mp->pixelmode) {
    				XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
    				XDrawLines(display, window, gc, p, 5, CoordModeOrigin);
    			}
    		}
    	} else {
    		if (mp->wireframe) {
    			XDrawLines(display, window, gc, p, 5, CoordModeOrigin);
    		} else {
    			XFillPolygon(display, window, gc, p, 4, Complex, CoordModeOrigin);
    
    			if (!mp->pixelmode) {
    				XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
    				XDrawLines(display, window, gc, p, 5, CoordModeOrigin);
    			}
    		}
    	}
    	mp->x++;
    	if (mp->x == WORLDWIDTH - 1) {
    		mp->y++;
    		mp->x = 0;
    	}
    	if (mp->y == WORLDWIDTH - 1)
    		mp->stage++;
    }
    
    void
    init_mountain(ModeInfo * mi)
    {
    	int         i, j, x, y;
    	XGCValues   gcv;
    	mountainstruct *mp;
    
    	if (mountains == NULL) {
    		if ((mountains = (mountainstruct *) calloc(MI_NUM_SCREENS(mi),
    					   sizeof (mountainstruct))) == NULL)
    			return;
    	}
    	mp = &mountains[MI_SCREEN(mi)];
    
    	mp->width = MI_WIDTH(mi);
    	mp->height = MI_HEIGHT(mi);
    	mp->pixelmode = (mp->width + mp->height < 200);
    	mp->stage = 0;
    	mp->time = 0;
    	mp->x = mp->y = 0;
    	if (MI_IS_FULLRANDOM(mi)) {
    		mp->joke = (Bool) (NRAND(10) == 0);
    		mp->wireframe = (Bool) (LRAND() & 1);
    	} else {
    		mp->joke = False;
    		mp->wireframe = MI_IS_WIREFRAME(mi);
    	}
    
    	if (mp->stippledGC == None) {
    		gcv.foreground = MI_WHITE_PIXEL(mi);
    		gcv.background = MI_BLACK_PIXEL(mi);
    		if ((mp->stippledGC = XCreateGC(MI_DISPLAY(mi), MI_WINDOW(mi),
    					  GCForeground | GCBackground, &gcv)) == None)
    			return;
    	}
    	MI_CLEARWINDOW(mi);
    
    	for (y = 0; y < (int) WORLDWIDTH; y++)
    		for (x = 0; x < (int) WORLDWIDTH; x++)
    			mp->h[x][y] = 0;
    
    	j = MI_COUNT(mi);
    	if (j < 0)
    		j = NRAND(-j) + 1;
    	for (i = 0; i < j; i++)
    		mp->h[RANGE_RAND(1, WORLDWIDTH - 1)][RANGE_RAND(1, WORLDWIDTH - 1)] =
    			NRAND(MAXHEIGHT);
    
    	for (y = 0; y < WORLDWIDTH; y++)
    		for (x = 0; x < WORLDWIDTH; x++)
    			spread(mp->h, x, y);
    
    	for (y = 0; y < WORLDWIDTH; y++)
    		for (x = 0; x < WORLDWIDTH; x++) {
    			mp->h[x][y] = mp->h[x][y] + NRAND(10) - 5;
    			if (mp->h[x][y] < 10)
    				mp->h[x][y] = 0;
    		}
    
    	if (MI_NPIXELS(mi) > 2)
    		mp->offset = NRAND(MI_NPIXELS(mi));
    	else
    		mp->offset = 0;
    }
    
    void
    draw_mountain(ModeInfo * mi)
    {
    	mountainstruct *mp;
    
    	if (mountains == NULL)
    			return;
    	mp = &mountains[MI_SCREEN(mi)];
    	if (mp->stippledGC == None)
    			return;
    
    	MI_IS_DRAWN(mi) = True;
    
    	switch (mp->stage) {
    		case 0:
    			drawamountain(mi);
    			break;
    		case 1:
    			if (++mp->time > MI_CYCLES(mi))
    				mp->stage++;
    			break;
    		case 2:
    			init_mountain(mi);
    			break;
    	}
    }
    
    void
    release_mountain(ModeInfo * mi)
    {
    	if (mountains != NULL) {
    		int         screen;
    
    		for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
    			mountainstruct *mp = &mountains[screen];
    
    			if (mp->stippledGC)
    				XFreeGC(MI_DISPLAY(mi), mp->stippledGC);
    		}
    		free(mountains);
    		mountains = (mountainstruct *) NULL;
    	}
    }
    
    void
    refresh_mountain(ModeInfo * mi)
    {
    	mountainstruct *mp;
    
    	if (mountains == NULL)
    			return;
    	mp = &mountains[MI_SCREEN(mi)];
    
    	MI_CLEARWINDOW(mi);
    	mp->x = 0;
    	mp->y = 0;
    }
    
    #endif /* MODE_mountain */