/* crystal --- polygons moving according to plane group rules */
#if !defined( lint ) && !defined( SABER )
-static const char sccsid[] = "@(#)crystal.c 4.07 97/11/24 xlockmore";
+static const char sccsid[] = "@(#)crystal.c 4.12 98/09/10 xlockmore";
#endif
* A moving polygon-mode. The polygons obey 2D-planegroup symmetry.
*
* Revision History:
+ * 10-Sep-98: new colour scheme
* 24-Feb-98: added option centre which turns on/off forcing the centre of
* the screen to be used
* added option maxsize which forces the dimensions to be chasen
* used
* When only one unit cell is drawn, it is chosen at random
* 18-Feb-98: added support for negative numbers with -nx and -ny meaning
- * "random" choice with geiven maximum
+ * "random" choice with given maximum
* added +/-grid option. If -cell is specified this option
* determines if one or all unit cells are drawn.
* -batchcount is now a parameter for all the objects on the screen
"*count: -500 \n" \
"*cycles: 200 \n" \
"*size: -15 \n" \
- "*ncolors: 200 \n" \
+ "*ncolors: 100 \n" \
"*fullrandom: True \n" \
"*verbose: False \n"
# include "xlockmore.h" /* in xscreensaver distribution */
#define DEF_NY1 1 /* number of unit cells in y-direction */
#define DEF_CENTRE "False"
#define DEF_MAXSIZE "False"
+#define DEF_CYCLE "True"
#define min(a,b) ((a) <= (b) ? (a) : (b))
+void release_crystal(ModeInfo * mi);
+
static int nx, ny;
-static Bool unit_cell, grid_cell, centre, maxsize;
+static Bool unit_cell, grid_cell, centre, maxsize, cycle_p;
static XrmOptionDescRec opts[] =
{
{"-cell", ".crystal.cell", XrmoptionNoArg, (caddr_t) "on"},
{"+cell", ".crystal.cell", XrmoptionNoArg, (caddr_t) "off"},
{"-grid", ".crystal.grid", XrmoptionNoArg, (caddr_t) "on"},
- {"+grid", ".crystal.grid", XrmoptionNoArg, (caddr_t) "off"}
+ {"+grid", ".crystal.grid", XrmoptionNoArg, (caddr_t) "off"},
+ {"-shift", ".crystal.shift", XrmoptionNoArg, (caddr_t) "on"},
+ {"+shift", ".crystal.shift", XrmoptionNoArg, (caddr_t) "off"}
};
static argtype vars[] =
{(caddr_t *) & centre, "centre", "Centre", DEF_CENTRE, t_Bool},
{(caddr_t *) & maxsize, "maxsize", "Maxsize", DEF_MAXSIZE, t_Bool},
{(caddr_t *) & unit_cell, "cell", "Cell", DEF_CELL, t_Bool},
- {(caddr_t *) & grid_cell, "grid", "Grid", DEF_GRID, t_Bool}
+ {(caddr_t *) & grid_cell, "grid", "Grid", DEF_GRID, t_Bool},
+ {(caddr_t *) & cycle_p, "shift", "Shift", DEF_CYCLE, t_Bool}
};
static OptionStruct desc[] =
{
{"-nx num", "Number of unit cells in x-direction"},
{"-ny num", "Number of unit cells in y-direction"},
- {"-/+centre", "turn on/off cenetering on screen"},
+ {"-/+centre", "turn on/off centering on screen"},
{"-/+maxsize", "turn on/off use of maximum part of screen"},
{"-/+cell", "turn on/off drawing of unit cell"},
- {"-/+grid", "turn on/off drawing of grid of unit cells (if -cell is on)"}
+ {"-/+grid", "turn on/off drawing of grid of unit cells (if -cell is on)"},
+ {"-/+shift", "turn on/off colour cycling"}
};
ModeSpecOpt crystal_opts =
crystalatom *atom;
GC gc;
Bool unit_cell, grid_cell;
+ Colormap cmap;
+ XColor *colors;
+ int ncolors;
+ Bool cycle_p, mono_p, no_colors;
+ unsigned long blackpixel, whitepixel, fg, bg;
+ int direction;
} crystalstruct;
static crystalstruct *crystals = NULL;
crystalstruct *cryst = &crystals[MI_SCREEN(mi)];
int i;
+ if (cryst->no_colors) {
+ release_crystal(mi);
+ init_crystal(mi);
+ return;
+ }
cryst->painted = True;
+ MI_IS_DRAWN(mi) = True;
XSetFunction(display, cryst->gc, GXxor);
+
+/* Rotate colours */
+ if (cryst->cycle_p) {
+ rotate_colors(display, cryst->cmap, cryst->colors, cryst->ncolors,
+ cryst->direction);
+ if (!(LRAND() % 1000))
+ cryst->direction = -cryst->direction;
+ }
for (i = 0; i < cryst->num_atom; i++) {
crystalatom *atom0;
atom0 = &cryst->atom[i];
- XSetForeground(display, cryst->gc, atom0->colour);
+ XSetForeground(display, cryst->gc, cryst->colors[atom0->colour].pixel);
crystal_drawatom(mi, atom0);
atom0->velocity[0] += NRAND(3) - 1;
atom0->velocity[0] = MAX(-20, MIN(20, atom0->velocity[0]));
crystalatom *atom0;
atom0 = &cryst->atom[i];
- XSetForeground(display, cryst->gc, atom0->colour);
+ XSetForeground(display, cryst->gc, cryst->colors[atom0->colour].pixel);
crystal_drawatom(mi, atom0);
}
XSetFunction(display, cryst->gc, GXcopy);
for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
crystalstruct *cryst = &crystals[screen];
+ MI_WHITE_PIXEL(mi) = cryst->whitepixel;
+ MI_BLACK_PIXEL(mi) = cryst->blackpixel;
+#ifndef STANDALONE
+ MI_FG_PIXEL(mi) = cryst->fg;
+ MI_BG_PIXEL(mi) = cryst->bg;
+#endif
+ if (cryst->colors && cryst->ncolors && !cryst->no_colors)
+ free_colors(display, cryst->cmap, cryst->colors, cryst->ncolors);
+ if (cryst->colors)
+ (void) free((void *) cryst->colors);
+ XFreeColormap(display, cryst->cmap);
if (cryst->gc != NULL)
XFreeGC(display, cryst->gc);
if (cryst->atom != NULL)
cryst = &crystals[MI_SCREEN(mi)];
if (!cryst->gc) {
+#ifndef STANDALONE
+ XColor color;
+
+ extern char *background;
+ extern char *foreground;
+
+ cryst->fg = MI_FG_PIXEL(mi);
+ cryst->bg = MI_BG_PIXEL(mi);
+#endif
+ cryst->blackpixel = MI_BLACK_PIXEL(mi);
+ cryst->whitepixel = MI_WHITE_PIXEL(mi);
+
+#ifdef STANDALONE
+ cryst->cmap = mi->xgwa.colormap;
+#else /* !STANDALONE */
+ cryst->cmap = XCreateColormap(display, window,
+ MI_VISUAL(mi), AllocNone);
+ XSetWindowColormap(display, window, cryst->cmap);
+
+ (void) XParseColor(display, cryst->cmap, "black", &color);
+ (void) XAllocColor(display, cryst->cmap, &color);
+ MI_BLACK_PIXEL(mi) = color.pixel;
+ (void) XParseColor(display, cryst->cmap, "white", &color);
+ (void) XAllocColor(display, cryst->cmap, &color);
+ MI_WHITE_PIXEL(mi) = color.pixel;
+
+ (void) XParseColor(display, cryst->cmap, background, &color);
+ (void) XAllocColor(display, cryst->cmap, &color);
+ MI_BG_PIXEL(mi) = color.pixel;
+ (void) XParseColor(display, cryst->cmap, foreground, &color);
+ (void) XAllocColor(display, cryst->cmap, &color);
+ MI_FG_PIXEL(mi) = color.pixel;
+#endif /* !STANDALONE */
+
+ cryst->colors = 0;
+ cryst->ncolors = 0;
if ((cryst->gc = XCreateGC(display, MI_WINDOW(mi),
(unsigned long) 0, (XGCValues *) NULL)) == None)
return;
cryst->painted = False;
XSetFunction(display, cryst->gc, GXxor);
+
/*Set up crystal data */
+ cryst->direction = (LRAND() & 1) ? 1 : -1;
if (MI_IS_FULLRANDOM(mi)) {
if (LRAND() & 1)
cryst->unit_cell = True;
if (cryst->gamma > 90.0) {
if (cryst->offset_w > 0)
cryst->offset_w = NRAND(cryst->offset_w) +
- cryst->b * sin((cryst->gamma - 90) * PI_RAD);
+ (int) (cryst->b * sin((cryst->gamma - 90) * PI_RAD));
else
cryst->offset_w = (int) (cryst->b * sin((cryst->gamma - 90) *
PI_RAD));
(int) ((iny + 1) * cryst->b * cos((cryst->gamma - 90) * PI_RAD)) + cryst->offset_h);
}
}
+/* Set up colour map */
+ if (cryst->colors && cryst->ncolors && !cryst->no_colors)
+ free_colors(display, cryst->cmap, cryst->colors, cryst->ncolors);
+ if (cryst->colors)
+ (void) free((void *) cryst->colors);
+ cryst->colors = 0;
+#ifdef STANDALONE
+ cryst->ncolors = get_integer_resource("ncolors", "Integer");
+#else
+ cryst->ncolors = MI_NCOLORS(mi);
+#endif
+ if (cryst->ncolors < 2)
+ cryst->ncolors = 2;
+ if (cryst->ncolors <= 2)
+ cryst->mono_p = True;
+ else
+ cryst->mono_p = False;
+
+ if (cryst->mono_p)
+ cryst->colors = 0;
+ else
+ cryst->colors = (XColor *) malloc(sizeof (*cryst->colors) * (cryst->ncolors + 1));
+#ifdef STANDALONE
+ cryst->cycle_p = has_writable_cells(mi->xgwa.screen, mi->xgwa.visual);
+#else
+ cryst->cycle_p = has_writable_cells(mi);
+#endif
+ if (cryst->cycle_p) {
+ if (MI_IS_FULLRANDOM(mi)) {
+ if (NRAND(8) == 7)
+ cryst->cycle_p = False;
+ else
+ cryst->cycle_p = True;
+ } else {
+ cryst->cycle_p = cycle_p;
+ }
+ }
+ if (!cryst->mono_p) {
+ if (!(LRAND() % 10))
+ make_random_colormap(
+#ifdef STANDALONE
+ mi->dpy, mi->xgwa.visual,
+#else
+ mi,
+#endif
+ cryst->cmap, cryst->colors, &cryst->ncolors,
+ True, True, &cryst->cycle_p
+#ifdef STANDALONE
+ , False
+#endif
+ );
+ else if (!(LRAND() % 2))
+ make_uniform_colormap(
+#ifdef STANDALONE
+ mi->dpy, mi->xgwa.visual,
+#else
+ mi,
+#endif
+ cryst->cmap, cryst->colors, &cryst->ncolors,
+ True, &cryst->cycle_p
+#ifdef STANDALONE
+ , False
+#endif
+ );
+ else
+ make_smooth_colormap(
+#ifdef STANDALONE
+ mi->dpy, mi->xgwa.visual,
+#else
+ mi,
+#endif
+ cryst->cmap, cryst->colors, &cryst->ncolors,
+ True, &cryst->cycle_p
+#ifdef STANDALONE
+ , False
+#endif
+ );
+ }
+ XInstallColormap(display, cryst->cmap);
+ if (cryst->ncolors < 2) {
+ cryst->ncolors = 2;
+ cryst->no_colors = True;
+ } else
+ cryst->no_colors = False;
+ if (cryst->ncolors <= 2)
+ cryst->mono_p = True;
+
+ if (cryst->mono_p)
+ cryst->cycle_p = False;
+
for (i = 0; i < cryst->num_atom; i++) {
crystalatom *atom0;
atom0 = &cryst->atom[i];
- if (MI_NPIXELS(mi) > 2)
- atom0->colour = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)));
+ if (cryst->ncolors > 2)
+ atom0->colour = NRAND(cryst->ncolors - 2) + 2;
else
atom0->colour = 1; /*Xor'red so WHITE may not be appropriate */
- XSetForeground(display, cryst->gc, atom0->colour);
+ XSetForeground(display, cryst->gc, cryst->colors[atom0->colour].pixel);
atom0->x0 = NRAND(cryst->a);
atom0->y0 = NRAND(cryst->b);
atom0->velocity[0] = NRAND(7) - 3;
crystal_setupatom(atom0, cryst->gamma);
crystal_drawatom(mi, atom0);
}
+ XSync(display, False);
XSetFunction(display, cryst->gc, GXcopy);
}