source: trunk/third/xscreensaver/hacks/flag.c @ 20148

Revision 20148, 13.3 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20147, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 4 -*-
2 * flag --- a waving flag
3 */
4#if 0
5static const char sccsid[] = "@(#)flag.c        4.02 97/04/01 xlockmore";
6#endif
7
8/* Copyright (c) 1996 Charles Vidal <vidalc@univ-mlv.fr>.
9 * PEtite demo X11 de charles vidal 15 05 96
10 * tourne sous Linux et SOLARIS
11 * thank's to Bas van Gaalen, Holland, PD, for his sources
12 * in pascal vous devez rajouter une ligne dans mode.c
13 *
14 * Permission to use, copy, modify, and distribute this software and its
15 * documentation for any purpose and without fee is hereby granted,
16 * provided that the above copyright notice appear in all copies and that
17 * both that copyright notice and this permission notice appear in
18 * supporting documentation.
19 *
20 * This file is provided AS IS with no warranties of any kind.  The author
21 * shall have no liability with respect to the infringement of copyrights,
22 * trade secrets or any patents by this file or any part thereof.  In no
23 * event will the author be liable for any lost revenue or profits or
24 * other special, indirect and consequential damages.
25 *
26 * Revision History:
27 * 22-Jan-98: jwz: made the flag wigglier; added xpm support.
28 *            (I tried to do this by re-porting from xlockmore, but the
29 *            current xlockmore version is completely inscrutable.)
30 * 13-May-97: jwz@jwz.org: turned into a standalone program.
31 *                        Made it able to animate arbitrary (runtime) text or bitmaps.
32 * 01-May-96: written.
33 */
34
35#ifdef STANDALONE
36# define PROGCLASS                                      "Flag"
37# define HACK_INIT                                      init_flag
38# define HACK_DRAW                                      draw_flag
39# define flag_opts                                      xlockmore_opts
40# define DEFAULTS       "*delay:                50000   \n"                     \
41                                        "*cycles:               1000    \n"                     \
42                                        "*size:                 -7      \n"                     \
43                                        "*ncolors:              200     \n"
44# define BRIGHT_COLORS
45# define UNIFORM_COLORS
46# define DEF_FONT                                       "-*-helvetica-bold-r-*-240-*"
47# define DEF_BITMAP                                     ""
48# define DEF_TEXT                                       ""
49# include "xlockmore.h"                         /* from the xscreensaver distribution */
50
51#include "xpm-pixmap.h"
52
53#include "images/bob.xbm"
54
55#else  /* !STANDALONE */
56# include "xlock.h"                                     /* from the xlockmore distribution */
57# include "flag.h"
58#endif /* !STANDALONE */
59
60
61#ifdef HAVE_UNAME
62# include <sys/utsname.h>
63#endif /* HAVE_UNAME */
64
65#ifdef STANDALONE
66static XrmOptionDescRec opts[] =
67{
68  { "-bitmap", ".flag.bitmap", XrmoptionSepArg, 0 },
69  { "-text",   ".flag.text",   XrmoptionSepArg, 0 }
70};
71
72#endif /* STANDALONE */
73
74ModeSpecOpt flag_opts = {
75#ifdef STANDALONE
76  2, opts, 0, NULL, NULL
77#else  /* !STANDALONE */
78  0, NULL, 0, NULL, NULL
79#endif /* STANDALONE */
80};
81
82#include <string.h>
83#include <X11/Xutil.h>
84
85#define MINSIZE 1
86#define MAXSCALE 8
87#define MINSCALE 2
88#define MAXINITSIZE 6
89#define MININITSIZE 2
90#define MINAMP 5
91#define MAXAMP 20
92#define MAXW(fp) (MAXSCALE * (fp)->image->width + 2 * MAXAMP + (fp)->pointsize)
93#define MAXH(fp) (MAXSCALE * (fp)->image->height+ 2 * MAXAMP + (fp)->pointsize)
94#define MINW(fp) (MINSCALE * (fp)->image->width + 2 * MINAMP + (fp)->pointsize)
95#define MINH(fp) (MINSCALE * (fp)->image->height+ 2 * MINAMP + (fp)->pointsize)
96#define ANGLES          360
97
98typedef struct {
99        int         samp;
100        int         sofs;
101        int         sidx;
102        int         x_flag, y_flag;
103        int         timer;
104        int         initialized;
105        int         stab[ANGLES];
106        Pixmap      cache;
107        int         width, height;
108        int         pointsize;
109        float      size;
110        float      inctaille;
111        int         startcolor;
112    XImage     *image;
113} flagstruct;
114
115static flagstruct *flags = NULL;
116
117static int
118random_num(int n)
119{
120        return ((int) (((float) LRAND() / MAXRAND) * (n + 1.0)));
121}
122
123static void
124initSintab(ModeInfo * mi)
125{
126        flagstruct *fp = &flags[MI_SCREEN(mi)];
127        int         i;
128
129  /*-
130   * change the periodicity of the sin formula : the maximum of the
131   * periocity seem to be 16 ( 2^4 ), after the drawing isn't good looking
132   */
133        int         periodicity = random_num(4);
134        int         puissance = 1;
135
136        /* for (i=0;i<periodicity;i++) puissance*=2; */
137        puissance <<= periodicity;
138        for (i = 0; i < ANGLES; i++)
139                fp->stab[i] = (int) (SINF(i * puissance * M_PI / ANGLES) * fp->samp) +
140                        fp->sofs;
141}
142
143static void
144affiche(ModeInfo * mi)
145{
146        Display    *display = MI_DISPLAY(mi);
147        int         x, y, xp, yp;
148        flagstruct *fp = &flags[MI_SCREEN(mi)];
149
150        for (x = 0; x < fp->image->width; x++)
151                for (y = fp->image->height-1; y >= 0; y--) {
152                        xp = (int) (fp->size * (float) x) +
153                                fp->stab[(fp->sidx + x + y) % ANGLES];
154                        yp = (int) (fp->size * (float) y) +
155                                fp->stab[(fp->sidx + 4 * x + y + y) % ANGLES];
156
157                        if (fp->image->depth > 1)
158                          XSetForeground(display, MI_GC(mi),
159                                                         XGetPixel(fp->image, x, y));
160                        else if (XGetPixel(fp->image, x, y))
161                                XSetForeground(display, MI_GC(mi), MI_WIN_BLACK_PIXEL(mi));
162                        else if (MI_NPIXELS(mi) <= 2)
163                                XSetForeground(display, MI_GC(mi), MI_WIN_WHITE_PIXEL(mi));
164                        else
165                                XSetForeground(display, MI_GC(mi),
166                                               MI_PIXEL(mi, (y + x + fp->sidx + fp->startcolor) % MI_NPIXELS(mi)));
167
168                        if (fp->pointsize <= 1)
169                                XDrawPoint(display, fp->cache, MI_GC(mi), xp, yp);
170                        else if (fp->pointsize < 6)
171                                XFillRectangle(display, fp->cache, MI_GC(mi), xp, yp,
172                                                           fp->pointsize, fp->pointsize);
173                        else
174                                XFillArc(display, fp->cache, MI_GC(mi), xp, yp,
175                                                 fp->pointsize, fp->pointsize, 0, 360*64);
176                }
177}
178
179#ifdef STANDALONE
180
181static void
182make_flag_bits(ModeInfo *mi)
183{
184  Display *dpy = MI_DISPLAY(mi);
185  flagstruct *fp = &flags[MI_SCREEN(mi)];
186  char *bitmap_name = get_string_resource ("bitmap", "Bitmap");
187  char *text = get_string_resource ("text", "Text");
188
189  /* If neither a bitmap nor text are specified, randomly select either
190         the builtin bitmap or builtin text. */
191  if ((!bitmap_name || !*bitmap_name) && (!text || !*text))
192        {
193          if (random() & 1)
194                {
195                  free(bitmap_name);
196                  bitmap_name = strdup("(default)");
197                }
198          else
199                {
200                  free(text);
201                  text = strdup("(default)");
202                }
203        }
204
205  if (bitmap_name &&
206          *bitmap_name &&
207          !!strcmp(bitmap_name, "(default)"))
208        {
209          Pixmap bitmap = 0;
210      int width = 0;
211      int height = 0;
212
213      bitmap = xpm_file_to_pixmap (dpy, MI_WINDOW (mi), bitmap_name,
214                                   &width, &height, 0);
215          if (bitmap)
216                {
217                  fp->image = XGetImage(dpy, bitmap, 0, 0, width, height, ~0L,
218                                                                ZPixmap);
219                  XFreePixmap(dpy, bitmap);
220                }
221        }
222  else if (text && *text)
223        {
224          char *text2;
225          char *fn = get_string_resource ("font", "Font");
226          char *def_fn = "fixed";
227          char *line, *token;
228          int width, height;
229          int lines;
230          int margin = 2;
231          int fg = 1;
232          int bg = 0;
233          Pixmap bitmap;
234          XFontStruct *font;
235          XCharStruct overall;
236      XGCValues gcv;
237          GC gc;
238
239          if (!strcmp(text, "(default)"))
240                {
241# ifdef HAVE_UNAME
242                  struct utsname uts;
243                  if (uname (&uts) < 0)
244                        {
245                          text = strdup("uname() failed");
246                        }
247                  else
248                        {
249                          char *s;
250                          if ((s = strchr(uts.nodename, '.')))
251                                *s = 0;
252                          text = (char *) malloc(strlen(uts.nodename) +
253                                                                         strlen(uts.sysname) +
254                                                                         strlen(uts.version) +
255                                                                         strlen(uts.release) + 10);
256# ifdef _AIX
257                          sprintf(text, "%s\n%s %s.%s",
258                                          uts.nodename, uts.sysname, uts.version, uts.release);
259# else  /* !_AIX */
260                          sprintf(text, "%s\n%s %s",
261                                          uts.nodename, uts.sysname, uts.release);
262# endif /* !_AIX */
263                        }
264#else   /* !HAVE_UNAME */
265# ifdef VMS
266                  text = strdup(getenv("SYS$NODE"));
267# else
268                  text = strdup("X\nScreen\nSaver");
269# endif
270#endif  /* !HAVE_UNAME */
271                }
272
273          while (*text &&
274                         (text[strlen(text)-1] == '\r' ||
275                          text[strlen(text)-1] == '\n'))
276                text[strlen(text)-1] = 0;
277
278          text2 = strdup(text);
279
280          if (!fn) fn = def_fn;
281      font = XLoadQueryFont (dpy, fn);
282      if (! font)
283                {
284                  fprintf(stderr, "%s: unable to load font %s; using %s\n",
285                                  progname, fn, def_fn);
286                  font = XLoadQueryFont (dpy, def_fn);
287                }
288
289          memset(&overall, 0, sizeof(overall));
290          token = text;
291          lines = 0;
292          while ((line = strtok(token, "\r\n")))
293                {
294                  XCharStruct o2;
295                  int ascent, descent, direction;
296                  token = 0;
297                  XTextExtents(font, line, strlen(line),
298                                           &direction, &ascent, &descent, &o2);
299                  overall.lbearing = MAX(overall.lbearing, o2.lbearing);
300                  overall.rbearing = MAX(overall.rbearing, o2.rbearing);
301                  lines++;
302                }
303
304          width = overall.lbearing + overall.rbearing + margin + margin + 1;
305          height = ((font->ascent + font->descent) * lines) + margin + margin;
306
307          bitmap = XCreatePixmap(dpy, MI_WINDOW(mi), width, height, 1);
308
309      gcv.font = font->fid;
310      gcv.foreground = bg;
311      gc = XCreateGC (dpy, bitmap, (GCFont | GCForeground), &gcv);
312          XFillRectangle(dpy, bitmap, gc, 0, 0, width, height);
313          XSetForeground(dpy, gc, fg);
314
315          token = text2;
316          lines = 0;
317          while ((line = strtok(token, "\r\n")))
318                {
319                  XCharStruct o2;
320                  int ascent, descent, direction, xoff;
321                  token = 0;
322
323                  XTextExtents(font, line, strlen(line),
324                                           &direction, &ascent, &descent, &o2);
325                  xoff = ((overall.lbearing + overall.rbearing) -
326                                  (o2.lbearing + o2.rbearing)) / 2;
327
328                  XDrawString(dpy, bitmap, gc,
329                                          overall.lbearing + margin + xoff,
330                                          ((font->ascent * (lines + 1)) +
331                                           (font->descent * lines) +
332                                           margin),
333                                          line, strlen(line));
334                  lines++;
335                }
336          free(text2);
337          XUnloadFont(dpy, font->fid);
338          XFree((XPointer) font);
339          XFreeGC(dpy, gc);
340
341          fp->image = XGetImage(dpy, bitmap, 0, 0, width, height, 1L, XYPixmap);
342          XFreePixmap(dpy, bitmap);
343        }
344  else
345        {
346      char *bits = (char *) malloc (sizeof(bob_bits));
347      memcpy (bits, bob_bits, sizeof(bob_bits));
348          fp->image = XCreateImage (dpy, MI_VISUAL(mi), 1, XYBitmap, 0,
349                                                                bits, bob_width, bob_height,
350                                                                8, 0);
351          fp->image->byte_order = LSBFirst;
352          fp->image->bitmap_bit_order = LSBFirst;
353        }
354
355  if (bitmap_name)
356        free (bitmap_name);
357  if (text)
358        free (text);
359}
360
361#else  /* !STANDALONE */
362
363static void
364make_flag_bits(ModeInfo *mi)
365{
366  flagstruct *fp = &flags[MI_SCREEN(mi)];
367  int x, y;
368  int w = flag_width;
369  int h = flag_height;
370  int i = 0;
371  fp->image =
372        XCreateImage(MI_DISPLAY(mi), MI_VISUAL(mi),
373                                 1, XYBitmap, 0,                                        /* dpth, fmt, offset */
374                                 (char *) calloc ((w+8) / 8, h),        /* data */
375                                 w, h, 8, 0);                                           /* w, h, pad, bpl */
376  /* Geez, what kinda goofy bit order is this?? */
377  for (x = 0; x < w; x++)
378        for (y = h-1; y >= 0; y--)
379          XPutPixel (fp->image, x, y, flag_bits[i++]);
380}
381
382#endif /* !STANDALONE */
383
384
385void
386init_flag(ModeInfo * mi)
387{
388        Display    *display = MI_DISPLAY(mi);
389        int         size = MI_SIZE(mi);
390        flagstruct *fp;
391
392        if (flags == NULL) {
393                if ((flags = (flagstruct *) calloc(MI_NUM_SCREENS(mi),
394                                               sizeof (flagstruct))) == NULL)
395                        return;
396        }
397        fp = &flags[MI_SCREEN(mi)];
398
399        make_flag_bits(mi);
400
401        fp->width = MI_WIN_WIDTH(mi);
402        fp->height = MI_WIN_HEIGHT(mi);
403
404        fp->samp = MAXAMP;      /* Amplitude */
405        fp->sofs = 20;          /* ???????? */
406        fp->pointsize = size;
407        if (size < -MINSIZE)
408                fp->pointsize = NRAND(-size - MINSIZE + 1) + MINSIZE;
409        if (fp->pointsize < MINSIZE ||
410        fp->width <= MAXW(fp) || fp->height <= MAXH(fp))
411                fp->pointsize = MINSIZE;
412        fp->size = MAXINITSIZE; /* Initial distance between pts */
413        fp->inctaille = 0.05;
414        fp->timer = 0;
415        fp->sidx = fp->x_flag = fp->y_flag = 0;
416
417        if (!fp->initialized) {
418                fp->initialized = True;
419                if (!(fp->cache = XCreatePixmap(display, MI_WINDOW(mi),
420                MAXW(fp), MAXH(fp), MI_WIN_DEPTH(mi))))
421#ifdef STANDALONE
422                  exit(-1);
423#else   /* !STANDALONE */
424                        error("%s: catastrophe memoire\n");
425#endif /* !STANDALONE */
426        }
427        XSetForeground(display, MI_GC(mi), MI_WIN_BLACK_PIXEL(mi));
428        XFillRectangle(display, fp->cache, MI_GC(mi),
429                       0, 0, MAXW(fp), MAXH(fp));
430        /* don't want any exposure events from XCopyArea */
431        XSetGraphicsExposures(display, MI_GC(mi), False);
432        if (MI_NPIXELS(mi) > 2)
433                fp->startcolor = NRAND(MI_NPIXELS(mi));
434        if (fp->width <= MAXW(fp) || fp->height <= MAXH(fp)) {
435                fp->samp = MINAMP;
436                fp->sofs = 0;
437                fp->x_flag = random_num(fp->width - MINW(fp));
438                fp->y_flag = random_num(fp->height - MINH(fp));
439        } else {
440                fp->samp = MAXAMP;
441                fp->sofs = 20;
442                fp->x_flag = random_num(fp->width - MAXW(fp));
443                fp->y_flag = random_num(fp->height - MAXH(fp));
444        }
445
446        initSintab(mi);
447
448        XClearWindow(display, MI_WINDOW(mi));
449}
450
451void release_flag(ModeInfo * mi);
452
453
454void
455draw_flag(ModeInfo * mi)
456{
457        Display    *display = MI_DISPLAY(mi);
458        Window      window = MI_WINDOW(mi);
459        flagstruct *fp = &flags[MI_SCREEN(mi)];
460
461        if (fp->width <= MAXW(fp) || fp->height <= MAXH(fp)) {
462                fp->size = MININITSIZE;
463                /* fp->pointsize = MINPOINTSIZE; */
464                XCopyArea(display, fp->cache, window, MI_GC(mi),
465                          0, 0, MINW(fp), MINH(fp), fp->x_flag, fp->y_flag);
466        } else {
467                if ((fp->size + fp->inctaille) > MAXSCALE)
468                        fp->inctaille = -fp->inctaille;
469                if ((fp->size + fp->inctaille) < MINSCALE)
470                        fp->inctaille = -fp->inctaille;
471                fp->size += fp->inctaille;
472                XCopyArea(display, fp->cache, window, MI_GC(mi),
473                          0, 0, MAXW(fp), MAXH(fp), fp->x_flag, fp->y_flag);
474        }
475        XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WIN_BLACK_PIXEL(mi));
476        XFillRectangle(display, fp->cache, MI_GC(mi),
477                       0, 0, MAXW(fp), MAXH(fp));
478        XFlush(display);
479        affiche(mi);
480        fp->sidx += 2;
481        fp->sidx %= (ANGLES * MI_NPIXELS(mi));
482        XFlush(display);
483        fp->timer++;
484        if ((MI_CYCLES(mi) > 0) && (fp->timer >= MI_CYCLES(mi)))
485      {
486        release_flag(mi);
487                init_flag(mi);
488      }
489}
490
491void
492release_flag(ModeInfo * mi)
493{
494        if (flags != NULL) {
495                int         screen;
496
497                for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
498                  {
499                        if (flags[screen].cache)
500                                XFreePixmap(MI_DISPLAY(mi), flags[screen].cache);
501                        if (flags[screen].image)
502                          XDestroyImage(flags[screen].image);
503                  }
504                (void) free((void *) flags);
505                flags = NULL;
506        }
507}
508
509void
510refresh_flag(ModeInfo * mi)
511{
512        /* Do nothing, it will refresh by itself */
513}
Note: See TracBrowser for help on using the repository browser.