"Fossies" - the Fresh Open Source Software Archive

Member "xlockmore-5.59/modes/qix.c" (8 Sep 2019, 14801 Bytes) of package /linux/misc/xlockmore-5.59.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "qix.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.58_vs_5.59.

    1 /* -*- Mode: C; tab-width: 4 -*- */
    2 /* qix --- vector swirl */
    3 
    4 #if 0
    5 static const char sccsid[] = "@(#)qix.c 5.00 2000/11/01 xlockmore";
    6 
    7 #endif
    8 
    9 /*-
   10  * Copyright (c) 1991 by Patrick J. Naughton.
   11  *
   12  * Permission to use, copy, modify, and distribute this software and its
   13  * documentation for any purpose and without fee is hereby granted,
   14  * provided that the above copyright notice appear in all copies and that
   15  * both that copyright notice and this permission notice appear in
   16  * supporting documentation.
   17  *
   18  * This file is provided AS IS with no warranties of any kind.  The author
   19  * shall have no liability with respect to the infringement of copyrights,
   20  * trade secrets or any patents by this file or any part thereof.  In no
   21  * event will the author be liable for any lost revenue or profits or
   22  * other special, indirect and consequential damages.
   23  *
   24  * Revision History:
   25  * 01-Nov-2000: Allocation checks
   26  * 03-Mar-1998: Combined with Darrick Brown's "geometry".
   27  * 10-May-1997: Compatible with xscreensaver
   28  * 29-Jul-1990: support for multiple screens.
   29  *              made check_bounds_?() a macro.
   30  *              fixed initial parameter setup.
   31  * 15-Dec-1989: Fix for proper skipping of {White,Black}Pixel() in colors.
   32  * 08-Oct-1989: Fixed bug in memory allocation in init_qix().
   33  *              Moved seconds() to an extern.
   34  * 23-Sep-1989: Switch to random() and fixed bug w/ less than 4 lines.
   35  * 20-Sep-1989: Lint.
   36  * 24-Mar-1989: Written.
   37  */
   38 
   39 #ifdef STANDALONE
   40 #define MODE_qix
   41 #define DEFAULTS "*delay: 30000 \n" \
   42     "*count: -5 \n" \
   43     "*cycles: 32 \n" \
   44     "*ncolors: 200 \n" \
   45     "*fullrandom: True \n" \
   46 
   47 # define reshape_qix 0
   48 # define qix_handle_event 0
   49 #define SMOOTH_COLORS
   50 #include "xlockmore.h"      /* in xscreensaver distribution */
   51 #else /* STANDALONE */
   52 #include "xlock.h"      /* in xlockmore distribution */
   53 #endif /* STANDALONE */
   54 
   55 #ifdef MODE_qix
   56 
   57 #define DEF_COMPLETE  "False"
   58 #define DEF_KALEID  "False"
   59 #define DEF_SOLID  "False"
   60 
   61 static Bool complete;
   62 static Bool kaleid;
   63 static Bool solid;
   64 
   65 static XrmOptionDescRec opts[] =
   66 {
   67     {(char *) "-complete", (char *) ".qix.complete", XrmoptionNoArg, (caddr_t) "on"},
   68     {(char *) "+complete", (char *) ".qix.complete", XrmoptionNoArg, (caddr_t) "off"},
   69     {(char *) "-kaleid", (char *) ".qix.kaleid", XrmoptionNoArg, (caddr_t) "on"},
   70     {(char *) "+kaleid", (char *) ".qix.kaleid", XrmoptionNoArg, (caddr_t) "off"},
   71     {(char *) "-solid", (char *) ".qix.solid", XrmoptionNoArg, (caddr_t) "on"},
   72     {(char *) "+solid", (char *) ".qix.solid", XrmoptionNoArg, (caddr_t) "off"}
   73 };
   74 static argtype vars[] =
   75 {
   76     {(void *) & complete, (char *) "complete", (char *) "Complete", (char *) DEF_COMPLETE, t_Bool},
   77     {(void *) & kaleid, (char *) "kaleid", (char *) "Kaleid", (char *) DEF_KALEID, t_Bool},
   78     {(void *) & solid, (char *) "solid", (char *) "Solid", (char *) DEF_SOLID, t_Bool}
   79 };
   80 static OptionStruct desc[] =
   81 {
   82     {(char *) "-/+complete", (char *) "turn on/off complete morphing graph"},
   83     {(char *) "-/+kaleid", (char *) "turn on/off complete kaleidoscope"},
   84     {(char *) "-/+solid", (char *) "turn on/off fills"}
   85 };
   86 
   87 ENTRYPOINT ModeSpecOpt qix_opts =
   88 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
   89 
   90 #ifdef USE_MODULES
   91 ModStruct   qix_description =
   92 {"qix", "init_qix", "draw_qix", "release_qix",
   93  "refresh_qix", "init_qix", "free_qix", &qix_opts,
   94  30000, -5, 32, 1, 64, 1.0, "",
   95  "Shows spinning lines a la Qix(tm)", 0, NULL};
   96 
   97 #endif
   98 
   99 /* How many segments to draw per cycle when redrawing */
  100 #define REDRAWSTEP 3
  101 #define MINPOINTS 2
  102 /*-
  103  * remember when complete: the number of lines to be drawn is 1+2+3+...+N or
  104  * N(N+1)/2
  105  */
  106 
  107 /* I forget now, did Newton discover this as a boy? */
  108 #define NEWT(n) (n*(n+1)/2)
  109 
  110 typedef struct {
  111     int         pix;
  112     int         first, last;
  113     XPoint     *delta, *position;
  114     int         npoints;
  115     int         offset;
  116     int         max_delta;
  117     int         width, height, mid, midx, midy;
  118     int         nlines, linecount;
  119     int         redrawing, redrawpos;
  120     XPoint     *lineq, *points;
  121     Bool        complete, kaleid, solid;
  122 } qixstruct;
  123 
  124 static qixstruct *qixs = (qixstruct *) NULL;
  125 
  126 #define check_bounds(qp, val, del, min, max)                \
  127 {                               \
  128     if ((val) < (min)) {                        \
  129     *(del) = NRAND((qp)->max_delta) + (qp)->offset; \
  130     } else if ((val) >= (max)) {                    \
  131     *(del) = -(NRAND((qp)->max_delta)) - (qp)->offset;  \
  132     }                               \
  133 }
  134 
  135 static void
  136 free_qix_screen(qixstruct *qp)
  137 {
  138     if (qp == NULL) {
  139         return;
  140     }
  141     if (qp->lineq != NULL) {
  142         free(qp->lineq);
  143         qp->lineq = (XPoint *) NULL;
  144     }
  145     if (qp->points != NULL) {
  146         free(qp->points);
  147         qp->points = (XPoint *) NULL;
  148     }
  149     if (qp->delta != NULL) {
  150         free(qp->delta);
  151         qp->delta = (XPoint *) NULL;
  152     }
  153     if (qp->position != NULL) {
  154         free(qp->position);
  155         qp->position = (XPoint *) NULL;
  156     }
  157     qp = NULL;
  158 }
  159 
  160 ENTRYPOINT void
  161 free_qix(ModeInfo * mi)
  162 {
  163     free_qix_screen(&qixs[MI_SCREEN(mi)]);
  164 }
  165 
  166 ENTRYPOINT void
  167 init_qix(ModeInfo * mi)
  168 {
  169     qixstruct  *qp;
  170     int         i;
  171 
  172     MI_INIT(mi, qixs);
  173     qp = &qixs[MI_SCREEN(mi)];
  174 
  175     qp->width = MI_WIDTH(mi);
  176     qp->height = MI_HEIGHT(mi);
  177     qp->mid = MAX(qp->width, qp->height) / 2;
  178     qp->midx = qp->width / 2;
  179     qp->midy = qp->height / 2;
  180     qp->max_delta = 16;
  181     qp->redrawing = 0;
  182     qp->linecount = 0;
  183 
  184     if (qp->width < 100) {  /* icon window */
  185         qp->max_delta /= 4;
  186     }
  187     qp->offset = qp->max_delta / 3;
  188     qp->last = 0;
  189     if (MI_NPIXELS(mi) > 2)
  190         qp->pix = NRAND(MI_NPIXELS(mi));
  191 
  192     qp->npoints = MI_COUNT(mi);
  193     if (qp->npoints < -MINPOINTS)
  194         qp->npoints = NRAND(qp->npoints - MINPOINTS + 1) + MINPOINTS;
  195     /* Absolute minimum */
  196     if (qp->npoints < MINPOINTS)
  197         qp->npoints = MINPOINTS;
  198 
  199     if (MI_IS_FULLRANDOM(mi))
  200         qp->complete = (Bool) (!NRAND(4));
  201     else
  202         qp->complete = complete;
  203 
  204     if (qp->complete) {
  205         qp->kaleid = False;
  206     } else {
  207         if (MI_IS_FULLRANDOM(mi))
  208             qp->kaleid = (Bool) (!NRAND(3));
  209         else
  210             qp->kaleid = kaleid;
  211     }
  212     if (qp->complete || qp->kaleid) {
  213         qp->solid = False;
  214     } else {
  215         if (MI_IS_FULLRANDOM(mi))
  216             qp->solid = (Bool) (LRAND() & 1);
  217         else
  218             qp->solid = solid;
  219     }
  220     if (qp->delta)
  221         free(qp->delta);
  222     if (qp->position)
  223         free(qp->position);
  224 
  225     if ((qp->delta = (XPoint *) malloc(qp->npoints *
  226             sizeof (XPoint))) == NULL) {
  227         free_qix_screen(qp);
  228         return;
  229     }
  230     if ((qp->position = (XPoint *) malloc(qp->npoints *
  231             sizeof (XPoint))) == NULL) {
  232         free_qix_screen(qp);
  233         return;
  234     }
  235     for (i = 0; i < qp->npoints; i++) {
  236         qp->delta[i].x = NRAND(qp->max_delta) + qp->offset;
  237         qp->delta[i].y = NRAND(qp->max_delta) + qp->offset;
  238         qp->position[i].x = NRAND(qp->width);
  239         qp->position[i].y = NRAND(qp->height);
  240     }
  241 
  242     qp->nlines = (qp->npoints == 2) ? (MI_CYCLES(mi) + 1) * 2 :
  243         ((MI_CYCLES(mi) + qp->npoints) / qp->npoints) * qp->npoints;
  244     if (qp->complete) {
  245         qp->max_delta /= 4;
  246         qp->nlines = qp->npoints;
  247     }
  248     if (qp->kaleid) {
  249         qp->nlines = (MI_CYCLES(mi) + 1) * 8;   /* Fudge it so its compatible */
  250     }
  251     if (qp->lineq) {
  252         free(qp->lineq);
  253         qp->lineq = (XPoint *) NULL;
  254     }
  255     if (qp->points) {
  256         free(qp->points);
  257         qp->points = (XPoint *) NULL;
  258     }
  259     if (!qp->kaleid) {
  260         if ((qp->lineq = (XPoint *) malloc(qp->nlines *
  261                 sizeof (XPoint))) == NULL) {
  262             free_qix_screen(qp);
  263             return;
  264         }
  265         for (i = 0; i < qp->nlines; i++)
  266             qp->lineq[i].x = qp->lineq[i].y = -1;   /* move initial point off screen */
  267         if (qp->solid) {
  268             if ((qp->points = (XPoint *) malloc(2 * qp->nlines *
  269                     sizeof (XPoint))) == NULL) {
  270                 free_qix_screen(qp);
  271                 return;
  272             }
  273         }
  274     }
  275     MI_CLEARWINDOW(mi);
  276 }
  277 
  278 ENTRYPOINT void
  279 draw_qix(ModeInfo * mi)
  280 {
  281     Display    *display = MI_DISPLAY(mi);
  282     GC          gc = MI_GC(mi);
  283     qixstruct  *qp = &qixs[MI_SCREEN(mi)];
  284     int         i, j, k, l, prev;
  285 
  286     qp->first = (qp->last + qp->npoints) % qp->nlines;
  287     prev = (qp->last - qp->npoints + qp->nlines) % qp->nlines;
  288 
  289     MI_IS_DRAWN(mi) = True;
  290 
  291 
  292     for (i = 0; i < qp->npoints; i++) {
  293         qp->position[i].x += qp->delta[i].x;
  294         qp->position[i].y += qp->delta[i].y;
  295         if (NRAND(20) < 1) {
  296             check_bounds(qp, qp->position[i].x, &qp->delta[i].x,
  297                      qp->width / 3, 2 * qp->width / 3);
  298         } else {
  299             check_bounds(qp, qp->position[i].x, &qp->delta[i].x, 0, qp->width);
  300         }
  301         if (NRAND(20) < 1) {
  302             check_bounds(qp, qp->position[i].y, &qp->delta[i].y,
  303                      qp->height / 3, 2 * qp->height / 3);
  304         } else {
  305             check_bounds(qp, qp->position[i].y, &qp->delta[i].y, 0, qp->height);
  306         }
  307     }
  308     XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
  309     if (qp->complete && qp->npoints > 3) {
  310         for (i = 0; i < qp->npoints - 1; i++)
  311             for (j = i + 1; j < qp->npoints; j++) {
  312                 XDrawLine(display, MI_WINDOW(mi), gc,
  313                     qp->lineq[qp->first + i].x,
  314                     qp->lineq[qp->first + i].y,
  315                     qp->lineq[qp->first + j].x,
  316                     qp->lineq[qp->first + j].y);
  317             }
  318     } else if (!qp->kaleid) {
  319         if (qp->solid) {
  320             if (qp->lineq[qp->last].x != -1 ||
  321                 qp->lineq[qp->last].y != -1) {
  322               for (i = 0; i < qp->npoints; i++) {
  323                 qp->points[i] = qp->lineq[qp->last + i];
  324                 qp->points[i + qp->npoints] =
  325                   qp->lineq[qp->first + qp->npoints - 1 - i];
  326               }
  327               XFillPolygon(display, MI_WINDOW(mi), gc,
  328                 qp->points, 2 * qp->npoints,
  329                 Complex, CoordModeOrigin);
  330             }
  331         } else {
  332             for (i = 1; i < qp->npoints +
  333                 ((qp->npoints == 2) ? -1 : 0); i++)
  334               XDrawLine(display, MI_WINDOW(mi), gc,
  335                 qp->lineq[qp->first + i - 1].x,
  336                 qp->lineq[qp->first + i - 1].y,
  337                 qp->lineq[qp->first + i].x,
  338                 qp->lineq[qp->first + i].y);
  339             XDrawLine(display, MI_WINDOW(mi), gc,
  340               qp->lineq[qp->first].x, qp->lineq[qp->first].y,
  341               qp->lineq[qp->first + qp->npoints - 1].x,
  342               qp->lineq[qp->first + qp->npoints - 1].y);
  343         }
  344     }
  345     if (MI_NPIXELS(mi) > 2) {
  346         XSetForeground(display, gc, MI_PIXEL(mi, qp->pix));
  347         if (++qp->pix >= MI_NPIXELS(mi))
  348             qp->pix = 0;
  349     } else
  350         XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
  351 
  352     if (qp->complete && qp->npoints > 3) {
  353         for (i = 0; i < qp->npoints - 1; i++)
  354             for (j = i + 1; j < qp->npoints; j++)
  355                 XDrawLine(display, MI_WINDOW(mi), gc,
  356                     qp->position[i].x, qp->position[i].y,
  357                        qp->position[j].x, qp->position[j].y);
  358     } else if (qp->kaleid) {
  359         for (i = 0; i < qp->npoints; i++) {
  360             XSegment    segs[8];
  361             XPoint      small[2];
  362 
  363             j = (i + 1) % qp->npoints;
  364             small[0].x = ABS(qp->position[i].x - qp->mid);
  365             small[0].y = ABS(qp->position[i].y - qp->mid);
  366             small[1].x = ABS(qp->position[j].x - qp->mid);
  367             small[1].y = ABS(qp->position[j].y - qp->mid);
  368             segs[0].x1 = qp->midx + small[0].x;
  369             segs[0].y1 = qp->midy + small[0].y;
  370             segs[0].x2 = qp->midx + small[1].x;
  371             segs[0].y2 = qp->midy + small[1].y;
  372             segs[1].x1 = qp->midx - small[0].x;
  373             segs[1].y1 = qp->midy + small[0].y;
  374             segs[1].x2 = qp->midx - small[1].x;
  375             segs[1].y2 = qp->midy + small[1].y;
  376             segs[2].x1 = qp->midx - small[0].x;
  377             segs[2].y1 = qp->midy - small[0].y;
  378             segs[2].x2 = qp->midx - small[1].x;
  379             segs[2].y2 = qp->midy - small[1].y;
  380             segs[3].x1 = qp->midx + small[0].x;
  381             segs[3].y1 = qp->midy - small[0].y;
  382             segs[3].x2 = qp->midx + small[1].x;
  383             segs[3].y2 = qp->midy - small[1].y;
  384             segs[4].x1 = qp->midx + small[0].y;
  385             segs[4].y1 = qp->midy + small[0].x;
  386             segs[4].x2 = qp->midx + small[1].y;
  387             segs[4].y2 = qp->midy + small[1].x;
  388             segs[5].x1 = qp->midx + small[0].y;
  389             segs[5].y1 = qp->midy - small[0].x;
  390             segs[5].x2 = qp->midx + small[1].y;
  391             segs[5].y2 = qp->midy - small[1].x;
  392             segs[6].x1 = qp->midx - small[0].y;
  393             segs[6].y1 = qp->midy - small[0].x;
  394             segs[6].x2 = qp->midx - small[1].y;
  395             segs[6].y2 = qp->midy - small[1].x;
  396             segs[7].x1 = qp->midx - small[0].y;
  397             segs[7].y1 = qp->midy + small[0].x;
  398             segs[7].x2 = qp->midx - small[1].y;
  399             segs[7].y2 = qp->midy + small[1].x;
  400             XDrawSegments(display, MI_WINDOW(mi), gc, segs, 8);
  401             if (qp->npoints == 2)   /* do not repeat drawing the same line */
  402                 break;
  403         }
  404         if (++qp->linecount >= qp->nlines) {
  405             qp->linecount = 0;
  406             MI_CLEARWINDOW(mi);
  407         }
  408     } else {
  409         if (qp->solid) {
  410             if (qp->lineq[prev].x != -1 ||
  411                 qp->lineq[prev].y != -1) {
  412               for (i = 0; i < qp->npoints; i++) {
  413                 qp->points[i] = qp->lineq[prev + i];
  414                 qp->points[i + qp->npoints] =
  415                   qp->position[qp->npoints - 1 - i];
  416               }
  417               XFillPolygon(display, MI_WINDOW(mi), gc,
  418                 qp->points, 2 * qp->npoints,
  419                 Complex, CoordModeOrigin);
  420             }
  421         } else {
  422             for (i = 1; i < qp->npoints + ((qp->npoints == 2) ? -1 : 0); i++)
  423                 XDrawLine(display, MI_WINDOW(mi), gc,
  424                     qp->position[i - 1].x,
  425                     qp->position[i - 1].y,
  426                     qp->position[i].x,
  427                     qp->position[i].y);
  428             XDrawLine(display, MI_WINDOW(mi), gc,
  429                 qp->position[0].x, qp->position[0].y,
  430                 qp->position[qp->npoints - 1].x,
  431                 qp->position[qp->npoints - 1].y);
  432         }
  433     }
  434 
  435     if (!qp->kaleid)
  436         for (i = 0; i < qp->npoints; i++) {
  437             qp->lineq[qp->last].x = qp->position[i].x;
  438             qp->lineq[qp->last].y = qp->position[i].y;
  439             qp->last++;
  440             if (qp->last >= qp->nlines)
  441                 qp->last = 0;
  442         }
  443     if (qp->redrawing) {
  444         for (i = 0; i < REDRAWSTEP; i++) {
  445             int jold = (qp->last - qp->redrawpos + qp->nlines - qp->npoints) % qp->nlines;
  446 
  447             j = (qp->first - qp->redrawpos + qp->nlines - qp->npoints) % qp->nlines;
  448             if (qp->complete && qp->npoints > 3) {
  449                 for (k = 0; k < qp->npoints - 1; k++)
  450                     for (l = k + 1; l < qp->npoints; l++)
  451                       XDrawLine(display, MI_WINDOW(mi), gc,
  452                         qp->lineq[j + k].x,
  453                         qp->lineq[j + k].y,
  454                         qp->lineq[j + l].x,
  455                         qp->lineq[j + l].y);
  456             } else if (!qp->kaleid) {
  457                 if (qp->solid) {
  458                   if (qp->lineq[jold].x != -1 ||
  459                       qp->lineq[jold].y != -1) {
  460                     for (i = 0; i < qp->npoints; i++) {
  461                       qp->points[i] = qp->lineq[jold + i];
  462                       qp->points[i + qp->npoints] =
  463                         qp->lineq[j + qp->npoints - 1 - i];
  464                     }
  465                     XFillPolygon(display, MI_WINDOW(mi), gc,
  466                       qp->points, 2 * qp->npoints,
  467                       Complex, CoordModeOrigin);
  468                   }
  469                 } else {
  470                   for (k = 1; k < qp->npoints +
  471                       ((qp->npoints == 2) ? -1 : 0); k++)
  472                     XDrawLine(display, MI_WINDOW(mi), gc,
  473                       qp->lineq[j + k - 1].x,
  474                       qp->lineq[j + k - 1].y,
  475                       qp->lineq[j + k].x,
  476                       qp->lineq[j + k].y);
  477                   XDrawLine(display, MI_WINDOW(mi), gc,
  478                     qp->lineq[j].x, qp->lineq[j].y,
  479                     qp->lineq[j + qp->npoints - 1].x,
  480                     qp->lineq[j + qp->npoints - 1].y);
  481                 }
  482             }
  483             qp->redrawpos += qp->npoints;
  484             if (qp->redrawpos >= qp->nlines - qp->npoints) {
  485                 qp->redrawing = 0;
  486                 break;
  487             }
  488         }
  489     }
  490 }
  491 
  492 ENTRYPOINT void
  493 release_qix(ModeInfo * mi)
  494 {
  495     if (qixs != NULL) {
  496         int         screen;
  497 
  498         for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
  499             free_qix_screen(&qixs[screen]);
  500         free(qixs);
  501         qixs = (qixstruct *) NULL;
  502     }
  503 }
  504 
  505 #ifndef STANDALONE
  506 ENTRYPOINT void
  507 refresh_qix(ModeInfo * mi)
  508 {
  509     qixstruct  *qp = &qixs[MI_SCREEN(mi)];
  510 
  511     MI_CLEARWINDOW(mi);
  512     qp->redrawing = 1;
  513     qp->redrawpos = 0;
  514 }
  515 #endif
  516 
  517 XSCREENSAVER_MODULE ("Qix", qix)
  518 
  519 #endif /* MODE_qix */