619 lines
17 KiB
C
619 lines
17 KiB
C
|
/* -*- Mode: C; tab-width: 4 -*- */
|
||
|
/* goop --- goop from a lava lamp */
|
||
|
|
||
|
#if !defined( lint ) && !defined( SABER )
|
||
|
static const char sccsid[] = "@(#)goop.c 5.00 2000/11/01 xlockmore";
|
||
|
|
||
|
#endif
|
||
|
|
||
|
/*-
|
||
|
* Copyright (c) 1997 by Jamie Zawinski
|
||
|
*
|
||
|
* 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
|
||
|
* 24-Mar-1998: xlock version David Bagley <bagleyd@tux.org>
|
||
|
* 1997: xscreensaver version Jamie Zawinski <jwz@jwz.org>
|
||
|
*/
|
||
|
|
||
|
/*-
|
||
|
* original copyright
|
||
|
* xscreensaver, Copyright (c) 1997 Jamie Zawinski <jwz@jwz.org>
|
||
|
*
|
||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||
|
* the above copyright notice appear in all copies and that both that
|
||
|
* copyright notice and this permission notice appear in supporting
|
||
|
* documentation. No representations are made about the suitability of this
|
||
|
* software for any purpose. It is provided "as is" without express or
|
||
|
* implied warranty.
|
||
|
*/
|
||
|
|
||
|
/*-
|
||
|
* This is pretty compute-intensive, probably due to the large number of
|
||
|
* polygon fills. I tried introducing a scaling factor to make the spline
|
||
|
* code emit fewer line segments, but that made the edges very rough.
|
||
|
* However, tuning *maxVelocity, *elasticity and *delay can result in much
|
||
|
* smoother looking animation. I tuned these for a 1280x1024 Indy display,
|
||
|
* but I don't know whether these values will be reasonable for a slower
|
||
|
* machine...
|
||
|
*
|
||
|
* The more planes the better -- SGIs have a 12-bit pseudocolor display
|
||
|
* (4096 colormap cells) which is mostly useless, except for this program,
|
||
|
* where it means you can have 11 or 12 mutually-transparent objects instead
|
||
|
* of only 7 or 8. But, if you are using the 12-bit visual, you should crank
|
||
|
* down the velocity and elasticity, or server slowness will cause the
|
||
|
* animation to look jerky (yes, it's sad but true, SGI's X server is
|
||
|
* perceptibly slower when using plane masks on a 12-bit visual than on an
|
||
|
* 8-bit visual.) Using -max-velocity 0.5 -elasticity 0.9 seems to work ok
|
||
|
* on my Indy R5k with visual 0x27 and the bottom-of-the-line 24-bit graphics
|
||
|
* board.
|
||
|
*
|
||
|
* It might look better if each blob had an outline, which was a *slightly*
|
||
|
* darker color than the center, to give them a bit more definition -- but
|
||
|
* that would mean using two planes per blob. (Or maybe allocating the
|
||
|
* outline colors outside of the plane-space? Then the outlines wouldn't be
|
||
|
* transparent, but maybe that wouldn't be so noticeable?)
|
||
|
*
|
||
|
* Oh, for an alpha channel... maybe I should rewrite this in GL. Then the
|
||
|
* blobs could have thickness, and curved edges with specular reflections...
|
||
|
*/
|
||
|
|
||
|
#ifdef STANDALONE
|
||
|
#define MODE_goop
|
||
|
#define PROGCLASS "Goop"
|
||
|
#define HACK_INIT init_goop
|
||
|
#define HACK_DRAW draw_goop
|
||
|
#define goop_opts xlockmore_opts
|
||
|
#define DEFAULTS "*delay: 40000 \n" \
|
||
|
"*count: 100 \n"
|
||
|
/*- Come back to this.
|
||
|
"*delay: 12000",
|
||
|
"*transparent: true",
|
||
|
"*additive: true",
|
||
|
"*xor: false",
|
||
|
"*count: 0",
|
||
|
"*planes: 0",
|
||
|
"*thickness: 5",
|
||
|
"*torque: 0.0075",
|
||
|
"*elasticity: 1.8",
|
||
|
"*maxVelocity: 1.2",
|
||
|
*/
|
||
|
#include "xlockmore.h" /* in xscreensaver distribution */
|
||
|
#else /* STANDALONE */
|
||
|
#include "xlock.h" /* in xlockmore distribution */
|
||
|
|
||
|
#endif /* STANDALONE */
|
||
|
#include <spline.h>
|
||
|
|
||
|
#ifdef MODE_goop
|
||
|
|
||
|
ModeSpecOpt goop_opts =
|
||
|
{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
|
||
|
|
||
|
#ifdef USE_MODULES
|
||
|
ModStruct goop_description =
|
||
|
{"goop", "init_goop", "draw_goop", "release_goop",
|
||
|
"init_goop", "init_goop", (char *) NULL, &goop_opts,
|
||
|
10000, -12, 1, 1, 64, 1.0, "",
|
||
|
"Shows goop from a lava lamp", 0, NULL};
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#define SCALE 10000 /* fixed-point math, for sub-pixel motion */
|
||
|
#define DEF_COUNT 12 /* When planes and count are 0, how many blobs. */
|
||
|
|
||
|
|
||
|
#define RANDSIGN() ((LRAND() & 1) ? 1 : -1)
|
||
|
|
||
|
typedef struct {
|
||
|
long x, y; /* position of midpoint */
|
||
|
long dx, dy; /* velocity and direction */
|
||
|
double torque; /* rotational speed */
|
||
|
double th; /* angle of rotation */
|
||
|
long elasticity; /* how fast they deform */
|
||
|
long max_velocity; /* speed limit */
|
||
|
long min_r, max_r; /* radius range */
|
||
|
int npoints; /* control points */
|
||
|
long *r; /* radii */
|
||
|
spline *splines;
|
||
|
} blob;
|
||
|
|
||
|
typedef struct {
|
||
|
int nblobs; /* number of blops per plane */
|
||
|
blob *blobs;
|
||
|
Pixmap pixmap;
|
||
|
unsigned long pixel;
|
||
|
GC gc;
|
||
|
} layer;
|
||
|
|
||
|
enum goop_mode {
|
||
|
transparent,
|
||
|
opaque,
|
||
|
xored,
|
||
|
outline
|
||
|
};
|
||
|
|
||
|
typedef struct {
|
||
|
enum goop_mode mode;
|
||
|
int width, height;
|
||
|
int nlayers;
|
||
|
layer *layers;
|
||
|
unsigned long background;
|
||
|
Pixmap pixmap;
|
||
|
GC pixmap_gc;
|
||
|
} goopstruct;
|
||
|
|
||
|
static goopstruct *goops = (goopstruct *) NULL;
|
||
|
|
||
|
static Bool
|
||
|
make_blob(blob * b, int maxx, int maxy, int size)
|
||
|
{
|
||
|
int i;
|
||
|
long mid;
|
||
|
|
||
|
maxx *= SCALE;
|
||
|
maxy *= SCALE;
|
||
|
size *= SCALE;
|
||
|
|
||
|
b->max_r = size / 2;
|
||
|
b->min_r = size / 10;
|
||
|
|
||
|
if (b->min_r < (5 * SCALE))
|
||
|
b->min_r = (5 * SCALE);
|
||
|
mid = ((b->min_r + b->max_r) / 2);
|
||
|
|
||
|
b->torque = 0.0075; /* torque init */
|
||
|
b->elasticity = (long) (SCALE * 1.8); /* elasticity init */
|
||
|
b->max_velocity = (long) (SCALE * 1.2); /* max_velocity init */
|
||
|
|
||
|
b->x = NRAND(maxx);
|
||
|
b->y = NRAND(maxy);
|
||
|
|
||
|
b->dx = NRAND(b->max_velocity) * RANDSIGN();
|
||
|
b->dy = NRAND(b->max_velocity) * RANDSIGN();
|
||
|
b->th = (2.0 * M_PI) * LRAND() / MAXRAND * RANDSIGN();
|
||
|
b->npoints = (int) (LRAND() % 5) + 5;
|
||
|
|
||
|
b->splines = make_spline(b->npoints);
|
||
|
if ((b->r = (long *) malloc(sizeof (*b->r) * b->npoints)) == NULL)
|
||
|
return False;
|
||
|
for (i = 0; i < b->npoints; i++)
|
||
|
b->r[i] = ((LRAND() % mid) + (mid / 2)) * RANDSIGN();
|
||
|
return True;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
throb_blob(blob * b)
|
||
|
{
|
||
|
int i;
|
||
|
double frac = ((M_PI + M_PI) / b->npoints);
|
||
|
|
||
|
for (i = 0; i < b->npoints; i++) {
|
||
|
long r = b->r[i];
|
||
|
long ra = (r > 0 ? r : -r);
|
||
|
double th = (b->th > 0 ? b->th : -b->th);
|
||
|
long x, y;
|
||
|
|
||
|
/* place control points evenly around perimiter, shifted by theta */
|
||
|
x = b->x + (long) (ra * cos(i * frac + th));
|
||
|
y = b->y + (long) (ra * sin(i * frac + th));
|
||
|
|
||
|
b->splines->control_x[i] = x / SCALE;
|
||
|
b->splines->control_y[i] = y / SCALE;
|
||
|
|
||
|
/* alter the radius by a random amount, in the direction in which
|
||
|
it had been going (the sign of the radius indicates direction.) */
|
||
|
ra += (NRAND(b->elasticity) * (r > 0 ? 1 : -1));
|
||
|
r = ra * (r >= 0 ? 1 : -1);
|
||
|
|
||
|
/* If we've reached the end (too long or too short) reverse direction. */
|
||
|
if ((ra > b->max_r && r >= 0) ||
|
||
|
(ra < b->min_r && r < 0))
|
||
|
r = -r;
|
||
|
/* And reverse direction in mid-course once every 50 times. */
|
||
|
else if (!(LRAND() % 50))
|
||
|
r = -r;
|
||
|
|
||
|
b->r[i] = r;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
move_blob(blob * b, int maxx, int maxy)
|
||
|
{
|
||
|
maxx *= SCALE;
|
||
|
maxy *= SCALE;
|
||
|
|
||
|
b->x += b->dx;
|
||
|
b->y += b->dy;
|
||
|
|
||
|
/* If we've reached the edge of the box, reverse direction. */
|
||
|
if ((b->x > maxx && b->dx >= 0) ||
|
||
|
(b->x < 0 && b->dx < 0)) {
|
||
|
b->dx = -b->dx;
|
||
|
}
|
||
|
if ((b->y > maxy && b->dy >= 0) ||
|
||
|
(b->y < 0 && b->dy < 0)) {
|
||
|
b->dy = -b->dy;
|
||
|
}
|
||
|
/* Alter velocity randomly. */
|
||
|
if (!(LRAND() % 10)) {
|
||
|
b->dx += (NRAND(b->max_velocity / 2) * RANDSIGN());
|
||
|
b->dy += (NRAND(b->max_velocity / 2) * RANDSIGN());
|
||
|
|
||
|
/* Throttle velocity */
|
||
|
if (b->dx > b->max_velocity || b->dx < -b->max_velocity)
|
||
|
b->dx /= 2;
|
||
|
if (b->dy > b->max_velocity || b->dy < -b->max_velocity)
|
||
|
b->dy /= 2;
|
||
|
} {
|
||
|
double th = b->th;
|
||
|
double d = (b->torque == 0 ? 0 : (b->torque) * LRAND() / MAXRAND);
|
||
|
|
||
|
if (th < 0)
|
||
|
th = -(th + d);
|
||
|
else
|
||
|
th += d;
|
||
|
|
||
|
if (th > (M_PI + M_PI))
|
||
|
th -= (M_PI + M_PI);
|
||
|
else if (th < 0)
|
||
|
th += (M_PI + M_PI);
|
||
|
|
||
|
b->th = (b->th > 0 ? th : -th);
|
||
|
}
|
||
|
|
||
|
/* Alter direction of rotation randomly. */
|
||
|
if (!(LRAND() % 100))
|
||
|
b->th *= -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
static void
|
||
|
draw_blob(Display * display, Drawable drawable, GC gc, blob * b,
|
||
|
Bool fill_p)
|
||
|
{
|
||
|
compute_closed_spline(b->splines);
|
||
|
#ifdef DEBUG
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < b->npoints; i++)
|
||
|
XDrawLine(display, drawable, gc, b->x / SCALE, b->y / SCALE,
|
||
|
b->splines->control_x[i], b->splines->control_y[i]);
|
||
|
}
|
||
|
#else
|
||
|
if (fill_p)
|
||
|
XFillPolygon(display, drawable, gc, b->splines->points, b->splines->n_points,
|
||
|
Nonconvex, CoordModeOrigin);
|
||
|
else
|
||
|
#endif
|
||
|
XDrawLines(display, drawable, gc, b->splines->points, b->splines->n_points,
|
||
|
CoordModeOrigin);
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
make_layer(ModeInfo * mi, layer * l, int nblobs)
|
||
|
{
|
||
|
int i;
|
||
|
int blob_min, blob_max;
|
||
|
XGCValues gcv;
|
||
|
int width = MI_WIDTH(mi), height = MI_HEIGHT(mi);
|
||
|
|
||
|
l->nblobs = nblobs;
|
||
|
|
||
|
if ((l->blobs = (blob *) calloc(l->nblobs, sizeof (blob))) == NULL)
|
||
|
return False;
|
||
|
|
||
|
blob_max = (width < height ? width : height) / 2;
|
||
|
blob_min = (blob_max * 2) / 3;
|
||
|
for (i = 0; i < l->nblobs; i++)
|
||
|
if (!make_blob(&(l->blobs[i]), width, height, (int) (LRAND() %
|
||
|
(blob_max - blob_min + 1)) + blob_min))
|
||
|
return False;
|
||
|
|
||
|
if ((l->pixmap = XCreatePixmap(MI_DISPLAY(mi), MI_WINDOW(mi),
|
||
|
width, height, 1)) == None)
|
||
|
return False;
|
||
|
if ((l->gc = XCreateGC(MI_DISPLAY(mi), l->pixmap, 0, &gcv)) == None)
|
||
|
return False;
|
||
|
return True;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
draw_layer_plane(Display * display, layer * layer_plane, int width, int height)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
XSetForeground(display, layer_plane->gc, 1L);
|
||
|
XFillRectangle(display, layer_plane->pixmap, layer_plane->gc,
|
||
|
0, 0, width, height);
|
||
|
XSetForeground(display, layer_plane->gc, 0L);
|
||
|
for (i = 0; i < layer_plane->nblobs; i++) {
|
||
|
throb_blob(&(layer_plane->blobs[i]));
|
||
|
move_blob(&(layer_plane->blobs[i]), width, height);
|
||
|
draw_blob(display, layer_plane->pixmap, layer_plane->gc,
|
||
|
&(layer_plane->blobs[i]), True);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
static void
|
||
|
draw_layer_blobs(Display * display, Drawable drawable, GC gc,
|
||
|
layer * layer_plane, int width, int height,
|
||
|
Bool fill_p)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < layer_plane->nblobs; i++) {
|
||
|
throb_blob(&(layer_plane->blobs[i]));
|
||
|
move_blob(&(layer_plane->blobs[i]), width, height);
|
||
|
draw_blob(display, drawable, gc, &(layer_plane->blobs[i]), fill_p);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
free_goop(Display * display, goopstruct * gp)
|
||
|
{
|
||
|
int l;
|
||
|
|
||
|
if (gp->layers != NULL) {
|
||
|
for (l = 0; l < gp->nlayers; l++) {
|
||
|
if (gp->layers[l].blobs != NULL) {
|
||
|
int b;
|
||
|
|
||
|
for (b = 0; b < gp->layers[l].nblobs; b++) {
|
||
|
if (gp->layers[l].blobs[b].r != NULL)
|
||
|
free(gp->layers[l].blobs[b].r);
|
||
|
free_spline(gp->layers[l].blobs[b].splines);
|
||
|
}
|
||
|
free(gp->layers[l].blobs);
|
||
|
}
|
||
|
if (gp->layers[l].gc != None)
|
||
|
XFreeGC(display, gp->layers[l].gc);
|
||
|
if (gp->layers[l].pixmap != None)
|
||
|
XFreePixmap(display, gp->layers[l].pixmap);
|
||
|
}
|
||
|
free(gp->layers);
|
||
|
gp->layers = (layer *) NULL;
|
||
|
}
|
||
|
if (gp->pixmap_gc != None) {
|
||
|
XFreeGC(display, gp->pixmap_gc);
|
||
|
gp->pixmap_gc = None;
|
||
|
}
|
||
|
if (gp->pixmap != None) {
|
||
|
XFreePixmap(display, gp->pixmap);
|
||
|
gp->pixmap = None;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
init_goop(ModeInfo * mi)
|
||
|
{
|
||
|
Display *display = MI_DISPLAY(mi);
|
||
|
Window window = MI_WINDOW(mi);
|
||
|
int i;
|
||
|
XGCValues gcv;
|
||
|
int nblobs;
|
||
|
unsigned long *plane_masks = NULL;
|
||
|
unsigned long base_pixel = 0;
|
||
|
goopstruct *gp;
|
||
|
|
||
|
if (goops == NULL) {
|
||
|
if ((goops = (goopstruct *) calloc(MI_NUM_SCREENS(mi),
|
||
|
sizeof (goopstruct))) == NULL)
|
||
|
return;
|
||
|
}
|
||
|
gp = &goops[MI_SCREEN(mi)];
|
||
|
|
||
|
gp->mode = (False /* xor init */ ? xored
|
||
|
: (True /* transparent init */ ? transparent : opaque));
|
||
|
|
||
|
gp->width = MI_WIDTH(mi);
|
||
|
gp->height = MI_HEIGHT(mi);
|
||
|
|
||
|
free_goop(display, gp);
|
||
|
|
||
|
gp->nlayers = 0; /* planes init */
|
||
|
if (gp->nlayers <= 0)
|
||
|
gp->nlayers = (int) (LRAND() % (MI_DEPTH(mi) - 2)) + 2;
|
||
|
if ((gp->layers = (layer *) calloc(gp->nlayers, sizeof (layer))) == NULL) {
|
||
|
return; /* free_goop just ran */
|
||
|
}
|
||
|
|
||
|
if ((MI_NPIXELS(mi) < 2) && gp->mode == transparent)
|
||
|
gp->mode = opaque;
|
||
|
|
||
|
/* Try to allocate some color planes before committing to nlayers.
|
||
|
*/
|
||
|
#if 0
|
||
|
if (gp->mode == transparent) {
|
||
|
Bool additive_p = True; /* additive init */
|
||
|
int nplanes = gp->nlayers;
|
||
|
|
||
|
/* allocate_alpha_colors (display, MI_COLORMAP(mi), &nplanes, additive_p, &plane_masks,
|
||
|
&base_pixel); *//* COME BACK */
|
||
|
if (nplanes > 1)
|
||
|
gp->nlayers = nplanes;
|
||
|
else {
|
||
|
(void) fprintf(stderr,
|
||
|
"could not allocate any color planes; turning transparency off.\n");
|
||
|
gp->mode = opaque;
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
if (gp->mode == transparent)
|
||
|
gp->mode = opaque;
|
||
|
#endif
|
||
|
|
||
|
nblobs = MI_COUNT(mi);
|
||
|
if (nblobs < 0) {
|
||
|
nblobs = NRAND(-nblobs) + 1; /* Add 1 so its not too boring */
|
||
|
} {
|
||
|
int *lblobs;
|
||
|
int total = DEF_COUNT;
|
||
|
|
||
|
if ((lblobs = (int *) calloc(gp->nlayers,
|
||
|
sizeof (int))) == NULL) {
|
||
|
free_goop(display, gp);
|
||
|
return;
|
||
|
}
|
||
|
if (nblobs <= 0)
|
||
|
while (total)
|
||
|
for (i = 0; total && i < gp->nlayers; i++)
|
||
|
lblobs[i]++, total--;
|
||
|
for (i = 0; i < gp->nlayers; i++)
|
||
|
if (!make_layer(mi, &(gp->layers[i]),
|
||
|
(nblobs > 0 ? nblobs : lblobs[i])))
|
||
|
free_goop(display, gp);
|
||
|
free(lblobs);
|
||
|
}
|
||
|
|
||
|
if (gp->mode == transparent && plane_masks) {
|
||
|
for (i = 0; i < gp->nlayers; i++)
|
||
|
gp->layers[i].pixel = base_pixel | plane_masks[i];
|
||
|
gp->background = base_pixel;
|
||
|
}
|
||
|
if (plane_masks != NULL)
|
||
|
free(plane_masks);
|
||
|
|
||
|
if (gp->mode != transparent) {
|
||
|
gp->background = 0; /* init */
|
||
|
|
||
|
for (i = 0; i < gp->nlayers; i++) {
|
||
|
if (MI_NPIXELS(mi) > 2)
|
||
|
gp->layers[i].pixel = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)));
|
||
|
else
|
||
|
gp->layers[i].pixel = MI_WHITE_PIXEL(mi);
|
||
|
}
|
||
|
}
|
||
|
if ((gp->pixmap = XCreatePixmap(display, window,
|
||
|
MI_WIDTH(mi), MI_HEIGHT(mi),
|
||
|
(gp->mode == xored ? 1 : MI_DEPTH(mi)))) == None) {
|
||
|
free_goop(display, gp);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
gcv.background = gp->background;
|
||
|
gcv.foreground = 255; /* init */
|
||
|
gcv.line_width = 5; /* thickness init */
|
||
|
if ((gp->pixmap_gc = XCreateGC(display, gp->pixmap, GCLineWidth,
|
||
|
&gcv)) == None) {
|
||
|
free_goop(display, gp);
|
||
|
return;
|
||
|
}
|
||
|
MI_CLEARWINDOW(mi);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
draw_goop(ModeInfo * mi)
|
||
|
{
|
||
|
Display *display = MI_DISPLAY(mi);
|
||
|
Window window = MI_WINDOW(mi);
|
||
|
int i;
|
||
|
goopstruct *gp;
|
||
|
|
||
|
if (goops == NULL)
|
||
|
return;
|
||
|
gp = &goops[MI_SCREEN(mi)];
|
||
|
if (gp->layers == NULL)
|
||
|
return;
|
||
|
|
||
|
MI_IS_DRAWN(mi) = True;
|
||
|
switch (gp->mode) {
|
||
|
case transparent:
|
||
|
|
||
|
for (i = 0; i < gp->nlayers; i++)
|
||
|
draw_layer_plane(display, &(gp->layers[i]), gp->width, gp->height);
|
||
|
|
||
|
XSetForeground(display, gp->pixmap_gc, gp->background);
|
||
|
XSetPlaneMask(display, gp->pixmap_gc, AllPlanes);
|
||
|
XFillRectangle(display, gp->pixmap, gp->pixmap_gc, 0, 0,
|
||
|
gp->width, gp->height);
|
||
|
XSetForeground(display, gp->pixmap_gc, ~0L);
|
||
|
for (i = 0; i < gp->nlayers; i++) {
|
||
|
XSetPlaneMask(display, gp->pixmap_gc, gp->layers[i].pixel);
|
||
|
|
||
|
#if 0
|
||
|
XSetForeground (display, gp->pixmap_gc, ~0L);
|
||
|
XFillRectangle (display, gp->pixmap, gp->pixmap_gc, 0, 0,
|
||
|
gp->width, gp->height);
|
||
|
XSetForeground (display, gp->pixmap_gc, 0L);
|
||
|
#endif
|
||
|
draw_layer_blobs(display, gp->pixmap, gp->pixmap_gc,
|
||
|
&(gp->layers[i]), gp->width, gp->height,
|
||
|
True);
|
||
|
}
|
||
|
XCopyArea(display, gp->pixmap, window, MI_GC(mi), 0, 0,
|
||
|
gp->width, gp->height, 0, 0);
|
||
|
break;
|
||
|
|
||
|
case xored:
|
||
|
XSetFunction(display, gp->pixmap_gc, GXcopy);
|
||
|
XSetForeground(display, gp->pixmap_gc, 0);
|
||
|
XFillRectangle(display, gp->pixmap, gp->pixmap_gc, 0, 0,
|
||
|
gp->width, gp->height);
|
||
|
XSetFunction(display, gp->pixmap_gc, GXxor);
|
||
|
XSetForeground(display, gp->pixmap_gc, 1);
|
||
|
for (i = 0; i < gp->nlayers; i++)
|
||
|
draw_layer_blobs(display, gp->pixmap, gp->pixmap_gc,
|
||
|
&(gp->layers[i]), gp->width, gp->height,
|
||
|
(gp->mode != outline));
|
||
|
XCopyPlane(display, gp->pixmap, window, MI_GC(mi), 0, 0,
|
||
|
gp->width, gp->height, 0, 0, 1L);
|
||
|
break;
|
||
|
|
||
|
case opaque:
|
||
|
case outline:
|
||
|
XSetForeground(display, gp->pixmap_gc, MI_BLACK_PIXEL(mi));
|
||
|
XFillRectangle(display, gp->pixmap, gp->pixmap_gc, 0, 0,
|
||
|
gp->width, gp->height);
|
||
|
for (i = 0; i < gp->nlayers; i++) {
|
||
|
XSetForeground(display, gp->pixmap_gc, gp->layers[i].pixel);
|
||
|
draw_layer_blobs(display, gp->pixmap, gp->pixmap_gc,
|
||
|
&(gp->layers[i]), gp->width, gp->height,
|
||
|
(gp->mode != outline));
|
||
|
}
|
||
|
XCopyArea(display, gp->pixmap, window, MI_GC(mi), 0, 0,
|
||
|
gp->width, gp->height, 0, 0);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
if (MI_IS_VERBOSE(mi)) {
|
||
|
(void) fprintf(stderr,
|
||
|
"Weirdness in draw_goop()\n");
|
||
|
(void) fprintf(stderr,
|
||
|
"gp->mode = %d\n", gp->mode);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
release_goop(ModeInfo * mi)
|
||
|
{
|
||
|
if (goops != NULL) {
|
||
|
int screen;
|
||
|
|
||
|
for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
|
||
|
free_goop(MI_DISPLAY(mi), &goops[screen]);
|
||
|
free(goops);
|
||
|
goops = (goopstruct *) NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif /* MODE_goop */
|