summaryrefslogtreecommitdiffstats
path: root/hacks/flag.c
diff options
context:
space:
mode:
authorSimon Rettberg2018-10-16 10:08:48 +0200
committerSimon Rettberg2018-10-16 10:08:48 +0200
commitd3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch)
treecbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /hacks/flag.c
downloadxscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip
Original 5.40
Diffstat (limited to 'hacks/flag.c')
-rw-r--r--hacks/flag.c565
1 files changed, 565 insertions, 0 deletions
diff --git a/hacks/flag.c b/hacks/flag.c
new file mode 100644
index 0000000..f12c0bc
--- /dev/null
+++ b/hacks/flag.c
@@ -0,0 +1,565 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ * flag --- a waving flag
+ */
+#if 0
+static const char sccsid[] = "@(#)flag.c 4.02 97/04/01 xlockmore";
+#endif
+
+/* Copyright (c) 1996 Charles Vidal <vidalc@univ-mlv.fr>.
+ * PEtite demo X11 de charles vidal 15 05 96
+ * tourne sous Linux et SOLARIS
+ * thank's to Bas van Gaalen, Holland, PD, for his sources
+ * in pascal vous devez rajouter une ligne dans mode.c
+ *
+ * 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:
+ * 22-Jan-98: jwz: made the flag wigglier; added xpm support.
+ * (I tried to do this by re-porting from xlockmore, but the
+ * current xlockmore version is completely inscrutable.)
+ * 13-May-97: jwz@jwz.org: turned into a standalone program.
+ * Made it able to animate arbitrary (runtime) text or bitmaps.
+ * 01-May-96: written.
+ */
+
+#ifdef HAVE_COCOA
+# define DEF_FONT "Monaco 15"
+#else
+# define DEF_FONT "fixed"
+#endif
+
+#ifdef STANDALONE
+# define DEFAULTS "*delay: 50000 \n" \
+ "*cycles: 1000 \n" \
+ "*size: -7 \n" \
+ "*ncolors: 200 \n" \
+ "*bitmap: \n" \
+ "*font: " DEF_FONT "\n" \
+ "*text: \n" \
+ "*fpsSolid: true \n" \
+ "*lowrez: true \n" \
+
+# define BRIGHT_COLORS
+# define UNIFORM_COLORS
+# define release_flag 0
+# define reshape_flag 0
+# define flag_handle_event 0
+# include "xlockmore.h" /* from the xscreensaver distribution */
+
+#include "ximage-loader.h"
+#include "images/gen/bob_png.h"
+
+#else /* !STANDALONE */
+# include "xlock.h" /* from the xlockmore distribution */
+# include "flag.h"
+#endif /* !STANDALONE */
+
+
+#ifdef HAVE_UNAME
+# include <sys/utsname.h>
+#endif /* HAVE_UNAME */
+
+#ifdef STANDALONE
+static XrmOptionDescRec opts[] =
+{
+ { "-bitmap", ".flag.bitmap", XrmoptionSepArg, 0 },
+ { "-text", ".flag.text", XrmoptionSepArg, 0 }
+};
+
+#endif /* STANDALONE */
+
+ENTRYPOINT ModeSpecOpt flag_opts = {
+#ifdef STANDALONE
+ 2, opts, 0, NULL, NULL
+#else /* !STANDALONE */
+ 0, NULL, 0, NULL, NULL
+#endif /* STANDALONE */
+};
+
+#define MINSIZE 1
+#define MAXSCALE 8
+#define MINSCALE 2
+#define MAXINITSIZE 6
+#define MININITSIZE 2
+#define MINAMP 5
+#define MAXAMP 20
+#define MAXW(fp) (MAXSCALE * (fp)->image->width + 2 * MAXAMP + (fp)->pointsize)
+#define MAXH(fp) (MAXSCALE * (fp)->image->height+ 2 * MAXAMP + (fp)->pointsize)
+#define MINW(fp) (MINSCALE * (fp)->image->width + 2 * MINAMP + (fp)->pointsize)
+#define MINH(fp) (MINSCALE * (fp)->image->height+ 2 * MINAMP + (fp)->pointsize)
+#define ANGLES 360
+
+typedef struct {
+ int samp;
+ int sofs;
+ int sidx;
+ int x_flag, y_flag;
+ int timer;
+ int initialized;
+ int stab[ANGLES];
+ Bool dbufp;
+ Pixmap cache;
+ int width, height;
+ int pointsize;
+ float size;
+ float inctaille;
+ int startcolor;
+ XImage *image;
+} flagstruct;
+
+static flagstruct *flags = NULL;
+
+static int
+random_num(int n)
+{
+ return ((int) (((float) LRAND() / MAXRAND) * (n + 1.0)));
+}
+
+static void
+initSintab(ModeInfo * mi)
+{
+ flagstruct *fp = &flags[MI_SCREEN(mi)];
+ int i;
+
+ /*-
+ * change the periodicity of the sin formula : the maximum of the
+ * periocity seem to be 16 ( 2^4 ), after the drawing isn't good looking
+ */
+ int periodicity = random_num(4);
+ int puissance = 1;
+
+ /* for (i=0;i<periodicity;i++) puissance*=2; */
+ puissance <<= periodicity;
+ for (i = 0; i < ANGLES; i++)
+ fp->stab[i] = (int) (SINF(i * puissance * M_PI / ANGLES) * fp->samp) +
+ fp->sofs;
+}
+
+static void
+affiche(ModeInfo * mi)
+{
+ Display *display = MI_DISPLAY(mi);
+ int x, y, xp, yp;
+ flagstruct *fp = &flags[MI_SCREEN(mi)];
+
+ for (x = 0; x < fp->image->width; x++)
+ for (y = fp->image->height-1; y >= 0; y--) {
+ xp = (int) (fp->size * (float) x) +
+ fp->stab[(fp->sidx + x + y) % ANGLES];
+ yp = (int) (fp->size * (float) y) +
+ fp->stab[(fp->sidx + 4 * x + y + y) % ANGLES];
+
+ if (fp->image->depth > 1)
+ XSetForeground(display, MI_GC(mi),
+ XGetPixel(fp->image, x, y));
+ else if (XGetPixel(fp->image, x, y))
+ XSetForeground(display, MI_GC(mi), MI_WIN_BLACK_PIXEL(mi));
+ else if (MI_NPIXELS(mi) <= 2)
+ XSetForeground(display, MI_GC(mi), MI_WIN_WHITE_PIXEL(mi));
+ else
+ XSetForeground(display, MI_GC(mi),
+ MI_PIXEL(mi, (y + x + fp->sidx + fp->startcolor) % MI_NPIXELS(mi)));
+
+ if (fp->cache == MI_WINDOW(mi)) { /* not double-buffering */
+ xp += fp->x_flag;
+ yp += fp->y_flag;
+ }
+
+ if (fp->pointsize <= 1)
+ XDrawPoint(display, fp->cache, MI_GC(mi), xp, yp);
+ else if (fp->pointsize < 6)
+ XFillRectangle(display, fp->cache, MI_GC(mi), xp, yp,
+ fp->pointsize, fp->pointsize);
+ else
+ XFillArc(display, fp->cache, MI_GC(mi), xp, yp,
+ fp->pointsize, fp->pointsize, 0, 360*64);
+ }
+}
+
+#ifdef STANDALONE
+
+static void
+make_flag_bits(ModeInfo *mi)
+{
+ Display *dpy = MI_DISPLAY(mi);
+ flagstruct *fp = &flags[MI_SCREEN(mi)];
+ char *bitmap_name = get_string_resource (dpy, "bitmap", "Bitmap");
+ char *text = get_string_resource (dpy, "text", "Text");
+
+#ifdef HAVE_JWXYZ
+ bitmap_name = 0; /* #### always use default */
+#endif
+
+ /* If neither a bitmap nor text are specified, randomly select either
+ the builtin bitmap or builtin text. */
+ if ((!bitmap_name || !*bitmap_name) && (!text || !*text))
+ {
+ if (random() & 1)
+ {
+ free(bitmap_name);
+ bitmap_name = strdup("(default)");
+ }
+ else
+ {
+ free(text);
+ text = strdup("(default)");
+ }
+ }
+
+ if (bitmap_name &&
+ *bitmap_name &&
+ !!strcmp(bitmap_name, "(default)"))
+ {
+ Pixmap bitmap = 0;
+ int width = 0;
+ int height = 0;
+
+ bitmap = file_to_pixmap (dpy, MI_WINDOW (mi), bitmap_name,
+ &width, &height, 0);
+ if (bitmap)
+ {
+ fp->image = XGetImage(dpy, bitmap, 0, 0, width, height, ~0L,
+ ZPixmap);
+ XFreePixmap(dpy, bitmap);
+ }
+ }
+ else if (text && *text)
+ {
+ char *text2;
+ char *fn = get_string_resource (dpy, "font", "Font");
+ char *def_fn = "fixed";
+ char *line, *token;
+ int width, height;
+ int lines;
+ int margin = 2;
+ int fg = 1;
+ int bg = 0;
+ Pixmap bitmap;
+ XFontStruct *font;
+ XCharStruct overall;
+ XGCValues gcv;
+ GC gc;
+
+ if (!strcmp(text, "(default)"))
+ {
+# ifdef HAVE_UNAME
+ struct utsname uts;
+ if (uname (&uts) < 0)
+ {
+ text = strdup("uname() failed");
+ }
+ else
+ {
+ char *s;
+ if ((s = strchr(uts.nodename, '.')))
+ *s = 0;
+ text = (char *) malloc(strlen(uts.nodename) +
+ strlen(uts.sysname) +
+ strlen(uts.version) +
+ strlen(uts.release) + 10);
+# if defined(_AIX)
+ sprintf(text, "%s\n%s %s.%s",
+ uts.nodename, uts.sysname, uts.version, uts.release);
+# elif defined(__APPLE__) && !defined(USE_IPHONE) /* MacOS X + XDarwin */
+ {
+ const char *file =
+ "/System/Library/CoreServices/SystemVersion.plist";
+ FILE *f = fopen (file, "r");
+ char *pbv = 0, *pn = 0, *puvv = 0;
+ if (f) {
+ char *s, buf[255];
+
+ while (fgets (buf, sizeof(buf)-1, f)) {
+# define GRAB(S,V) \
+ if (strstr(buf, S)) { \
+ fgets (buf, sizeof(buf)-1, f); \
+ if ((s = strchr (buf, '>'))) V = strdup(s+1); \
+ if ((s = strchr (V, '<'))) *s = 0; \
+ }
+ GRAB ("ProductName", pn)
+ GRAB ("ProductBuildVersion", pbv)
+ GRAB ("ProductUserVisibleVersion", puvv)
+# undef GRAB
+ }
+ }
+ if (pbv)
+ sprintf (text, "%s\n%s\n%s",
+ uts.nodename, pn, puvv /*, uts.machine*/);
+ else
+ sprintf(text, "%s\n%s %s",
+ uts.nodename, uts.sysname, uts.release);
+ }
+# else
+ sprintf(text, "%s\n%s %s",
+ uts.nodename, uts.sysname, uts.release);
+# endif /* special system types */
+ }
+#else /* !HAVE_UNAME */
+# ifdef VMS
+ text = strdup(getenv("SYS$NODE"));
+# else
+ text = strdup("X\nScreen\nSaver");
+# endif
+#endif /* !HAVE_UNAME */
+ }
+
+ while (*text &&
+ (text[strlen(text)-1] == '\r' ||
+ text[strlen(text)-1] == '\n'))
+ text[strlen(text)-1] = 0;
+
+ text2 = strdup(text);
+
+ if (!fn) fn = def_fn;
+ font = load_font_retry (dpy, fn);
+
+ memset(&overall, 0, sizeof(overall));
+ token = text;
+ lines = 0;
+ while ((line = strtok(token, "\r\n")))
+ {
+ XCharStruct o2;
+ int ascent, descent, direction;
+ token = 0;
+ XTextExtents(font, line, strlen(line),
+ &direction, &ascent, &descent, &o2);
+ overall.lbearing = MAX(overall.lbearing, o2.lbearing);
+ overall.rbearing = MAX(overall.rbearing, o2.rbearing);
+ lines++;
+ }
+
+ width = overall.lbearing + overall.rbearing + margin + margin + 1;
+ height = ((font->ascent + font->descent) * lines) + margin + margin;
+
+ bitmap = XCreatePixmap(dpy, MI_WINDOW(mi), width, height, 1);
+
+ gcv.font = font->fid;
+ gcv.foreground = bg;
+ gc = XCreateGC (dpy, bitmap, (GCFont | GCForeground), &gcv);
+ XFillRectangle(dpy, bitmap, gc, 0, 0, width, height);
+ XSetForeground(dpy, gc, fg);
+
+ token = text2;
+ lines = 0;
+ while ((line = strtok(token, "\r\n")))
+ {
+ XCharStruct o2;
+ int ascent, descent, direction, xoff;
+ token = 0;
+
+ XTextExtents(font, line, strlen(line),
+ &direction, &ascent, &descent, &o2);
+ xoff = ((overall.lbearing + overall.rbearing) -
+ (o2.lbearing + o2.rbearing)) / 2;
+
+ XDrawString(dpy, bitmap, gc,
+ overall.lbearing + margin + xoff,
+ ((font->ascent * (lines + 1)) +
+ (font->descent * lines) +
+ margin),
+ line, strlen(line));
+ lines++;
+ }
+ free(text2);
+ XUnloadFont(dpy, font->fid);
+ XFree((XPointer) font);
+ XFreeGC(dpy, gc);
+
+ fp->image = XGetImage(dpy, bitmap, 0, 0, width, height, 1L, XYPixmap);
+ XFreePixmap(dpy, bitmap);
+ }
+
+
+ if (! fp->image)
+ {
+ XImage *im = image_data_to_ximage (dpy, MI_VISUAL(mi),
+ bob_png, sizeof(bob_png));
+ int x, y;
+
+ fp->image = XCreateImage (dpy, MI_VISUAL(mi), 1, XYBitmap, 0,
+ 0, im->width, im->height, 8, 0);
+ fp->image->data = malloc (fp->image->bytes_per_line * fp->image->height);
+
+ /* Convert deep image to 1 bit */
+ for (y = 0; y < im->height; y++)
+ {
+ for (x = 0; x < im->width; x++)
+ {
+ unsigned long p = XGetPixel (im, x, im->height-y-1);
+ if (! (p & 0xFF000000)) p = ~0; /* alpha -> white */
+ p = (p >> 16) & 0xFF; /* red */
+ XPutPixel (fp->image, x, y, p > 0x7F ? 0 : 1);
+ }
+ }
+ XDestroyImage (im);
+ }
+
+ if (bitmap_name)
+ free (bitmap_name);
+ if (text)
+ free (text);
+}
+
+#else /* !STANDALONE */
+
+static void
+make_flag_bits(ModeInfo *mi)
+{
+ flagstruct *fp = &flags[MI_SCREEN(mi)];
+ int x, y;
+ int w = flag_width;
+ int h = flag_height;
+ int i = 0;
+ fp->image =
+ XCreateImage(MI_DISPLAY(mi), MI_VISUAL(mi),
+ 1, XYBitmap, 0, /* dpth, fmt, offset */
+ (char *) calloc ((w+8) / 8, h), /* data */
+ w, h, 8, 0); /* w, h, pad, bpl */
+ /* Geez, what kinda goofy bit order is this?? */
+ for (x = 0; x < w; x++)
+ for (y = h-1; y >= 0; y--)
+ XPutPixel (fp->image, x, y, flag_bits[i++]);
+}
+
+#endif /* !STANDALONE */
+
+
+ENTRYPOINT void
+init_flag(ModeInfo * mi)
+{
+ Display *display = MI_DISPLAY(mi);
+ int size = MI_SIZE(mi);
+ flagstruct *fp;
+
+ MI_INIT (mi, flags);
+ fp = &flags[MI_SCREEN(mi)];
+
+ make_flag_bits(mi);
+ if (!fp->image) abort();
+
+ fp->width = MI_WIN_WIDTH(mi);
+ fp->height = MI_WIN_HEIGHT(mi);
+
+ fp->samp = MAXAMP; /* Amplitude */
+ fp->sofs = 20; /* ???????? */
+ fp->pointsize = size;
+ if (size < -MINSIZE)
+ fp->pointsize = NRAND(-size - MINSIZE + 1) + MINSIZE;
+ if (fp->pointsize < MINSIZE ||
+ fp->width <= MAXW(fp) || fp->height <= MAXH(fp))
+ fp->pointsize = MINSIZE;
+ fp->size = MAXINITSIZE; /* Initial distance between pts */
+ fp->inctaille = 0.05;
+ fp->timer = 0;
+ fp->sidx = fp->x_flag = fp->y_flag = 0;
+
+ if (!fp->initialized) {
+ fp->dbufp = True;
+# ifdef HAVE_JWXYZ /* Don't second-guess Quartz's double-buffering */
+ fp->dbufp = False;
+#endif
+ fp->initialized = True;
+ if (!fp->dbufp)
+ fp->cache = MI_WINDOW(mi); /* not double-buffering */
+ else
+ if (!(fp->cache = XCreatePixmap(display, MI_WINDOW(mi),
+ MAXW(fp), MAXH(fp),
+ MI_WIN_DEPTH(mi))))
+#ifdef STANDALONE
+ exit(-1);
+#else /* !STANDALONE */
+ error("%s: catastrophe memoire\n");
+#endif /* !STANDALONE */
+ }
+ XSetForeground(display, MI_GC(mi), MI_WIN_BLACK_PIXEL(mi));
+ XFillRectangle(display, fp->cache, MI_GC(mi),
+ 0, 0, MAXW(fp), MAXH(fp));
+ /* don't want any exposure events from XCopyArea */
+ XSetGraphicsExposures(display, MI_GC(mi), False);
+ if (MI_NPIXELS(mi) > 2)
+ fp->startcolor = NRAND(MI_NPIXELS(mi));
+ if (fp->width <= MAXW(fp) || fp->height <= MAXH(fp)) {
+ fp->samp = MINAMP;
+ fp->sofs = 0;
+ fp->x_flag = random_num(fp->width - MINW(fp));
+ fp->y_flag = random_num(fp->height - MINH(fp));
+ } else {
+ fp->samp = MAXAMP;
+ fp->sofs = 20;
+ fp->x_flag = random_num(fp->width - MAXW(fp));
+ fp->y_flag = random_num(fp->height - MAXH(fp));
+ }
+
+ initSintab(mi);
+
+ XClearWindow(display, MI_WINDOW(mi));
+}
+
+ENTRYPOINT void
+draw_flag(ModeInfo * mi)
+{
+ Display *display = MI_DISPLAY(mi);
+ Window window = MI_WINDOW(mi);
+ flagstruct *fp = &flags[MI_SCREEN(mi)];
+
+ if (!fp->image) abort();
+ if (fp->cache == window) { /* not double-buffering */
+ XClearWindow (display, window);
+ } else if (fp->width <= MAXW(fp) || fp->height <= MAXH(fp)) {
+ fp->size = MININITSIZE;
+ /* fp->pointsize = MINPOINTSIZE; */
+ XCopyArea(display, fp->cache, window, MI_GC(mi),
+ 0, 0, MINW(fp), MINH(fp), fp->x_flag, fp->y_flag);
+ } else {
+ if ((fp->size + fp->inctaille) > MAXSCALE)
+ fp->inctaille = -fp->inctaille;
+ if ((fp->size + fp->inctaille) < MINSCALE)
+ fp->inctaille = -fp->inctaille;
+ fp->size += fp->inctaille;
+ XCopyArea(display, fp->cache, window, MI_GC(mi),
+ 0, 0, MAXW(fp), MAXH(fp), fp->x_flag, fp->y_flag);
+ }
+ XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WIN_BLACK_PIXEL(mi));
+ XFillRectangle(display, fp->cache, MI_GC(mi),
+ 0, 0, MAXW(fp), MAXH(fp));
+ affiche(mi);
+ fp->sidx += 2;
+ fp->sidx %= (ANGLES * MI_NPIXELS(mi));
+ fp->timer++;
+ if ((MI_CYCLES(mi) > 0) && (fp->timer >= MI_CYCLES(mi)))
+ init_flag(mi);
+}
+
+ENTRYPOINT void
+free_flag(ModeInfo * mi)
+{
+ int screen = MI_SCREEN(mi);
+
+ if (flags == NULL)
+ return;
+
+ if (flags[screen].cache && flags[screen].dbufp)
+ XFreePixmap(MI_DISPLAY(mi), flags[screen].cache);
+ if (flags[screen].image)
+ XDestroyImage(flags[screen].image);
+}
+
+#ifndef STANDALONE
+ENTRYPOINT void
+refresh_flag(ModeInfo * mi)
+{
+ /* Do nothing, it will refresh by itself */
+}
+#endif
+
+XSCREENSAVER_MODULE ("Flag", flag)