X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Flmorph.c;h=f372c1eeff7c8463bda4cda0fe5c826c0c9fa7aa;hp=70c91eee893e5c730166100eaeb45be3c0f4fc6b;hb=0bd2eabab3e404c6769fe8f59b639275e960c415;hpb=c6b273ef7292ba10943694df1656b05203d7b62f diff --git a/hacks/lmorph.c b/hacks/lmorph.c index 70c91eee..f372c1ee 100644 --- a/hacks/lmorph.c +++ b/hacks/lmorph.c @@ -7,18 +7,37 @@ * DESCRIPTION Bilinear interpolation for morphing line shapes. * * WRITTEN BY Sverre H. Huseby Glenn T. Lines - * Maridalsvn. 122, leil 101 Frysjavn. 3, 5. etg. - * N-0461 Oslo N-0883 Oslo + * Kurvn. 30 Østgaardsgt. 5 + * N-0495 Oslo N-0474 Oslo * Norway Norway * - * Phone: +47 22 71 99 08 Phone: +47 22 23 71 99 - * E-mail: sverrehu@ifi.uio.no E-mail: gtl@si.sintef.no + * Phone: +47 901 63 579 Phone: +47 22 04 67 28 + * E-mail: sverrehu@online.no E-mail: gtl@si.sintef.no + * URL: http://home.sol.no/~sverrehu/ * * The original idea, and the bilinear interpolation * mathematics used, emerged in the head of the wise - * Glenn Terje Lines. + * Glenn T. Lines. * - * MODIFICATIONS march 1995 + * MODIFICATIONS june 1998 (shh) + * * Minor code cleanup. + * + * march 1997 (shh) + * * Added -mailfile option to allow checking for + * new mail while the screensaver is active. + * + * january 1997 (shh) + * * Some code reformatting. + * * Added possibility to use float arithmetic. + * * Added -figtype option. + * * Made color blue default. + * + * december 1995 (jwz) + * * Function headers converted from ANSI to K&R. + * * Added posibility for random number of steps, and + * made this the default. + * + * march 1995 (shh) * * Converted from an MS-Windows program to X Window. * **************************************************************************/ @@ -35,38 +54,43 @@ * * **************************************************************************/ -/* Define MARGINS to make some space around the figure */ -#define MARGINS /**/ +/* define MARGINS to make some space around the figure. */ +#define MARGINS + +/* define USE_FLOAT to avoid using integer calculations in + createPoints. integer calculation is supposed to be faster, but it + won't work for displays larger than 2048x2048 or so pixels. */ +#undef USE_FLOAT #define MAXFIGS 20 #define TWO_PI (2.0 * M_PI) #define RND(x) (random() % (x)) + +#define FT_OPEN 1 +#define FT_CLOSED 2 +#define FT_ALL (FT_OPEN | FT_CLOSED) + static int - cFig = 0, /* Number of figure arrays. */ - cPoint, /* Number of points in each array. */ - nWork, /* Current work array number. */ - nFrom, /* Current from array number. */ - nTo; /* Current to array number. */ -static long - delay; /* usecs to wait between updates. */ + numFigs = 0, /* number of figure arrays. */ + numPoints, /* number of points in each array. */ + nWork, /* current work array number. */ + nFrom, /* current from array number. */ + nTo, /* current to array number. */ + figType; +static long delay; /* usecs to wait between updates. */ static XPoint - *aWork[2], /* Working arrays. */ - *a[MAXFIGS], /* The figure arrays. */ - *aTmp, /* Used as source when interrupting morph */ - *aPrev, /* Previous points displayed. */ - *aCurr, /* The current points displayed. */ - *aFrom, /* Figure converting from. */ - *aTo; /* Figure converting to. */ -static double - gam, - maxGamma = 1.0, - delta_gam; -static GC - gcDraw, gcClear; -static Display - *dpy; -static Window - window; + *aWork[2], /* working arrays. */ + *a[MAXFIGS], /* the figure arrays. */ + *aTmp, /* used as source when interrupting morph */ + *aPrev, /* previous points displayed. */ + *aCurr, /* the current points displayed. */ + *aFrom, /* figure converting from. */ + *aTo; /* figure converting to. */ +static int scrWidth, scrHeight; +static double currGamma, maxGamma = 1.0, deltaGamma; +static GC gcDraw, gcClear; +static Display *dpy; +static Window window; @@ -79,20 +103,24 @@ static Window char *progclass = "LMorph"; char *defaults [] = { - "LMorph.background: black", - "LMorph.foreground: green", + ".background: black", + ".foreground: blue", "*points: 150", "*steps: 0", "*delay: 50000", + "*figtype: all", 0 }; XrmOptionDescRec options [] = { - { "-points", ".points", XrmoptionSepArg, 0 }, - { "-steps", ".steps", XrmoptionSepArg, 0 }, - { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-points", ".points", XrmoptionSepArg, 0 }, + { "-steps", ".steps", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-figtype", ".figtype", XrmoptionSepArg, 0 }, { 0, 0, 0, 0 } }; +int options_size = (sizeof (options) / sizeof (options[0])); + /************************************************************************** @@ -113,308 +141,220 @@ xmalloc(size_t size) return ret; } - - -static double frnd (void) -{ - /* - * Hm. for some reason the second line (using RAND_MAX) didn't - * work on some machines, so I always use the first. - */ -#ifndef dont_use_RAND_MAX - return (double) (random() & 0x7FFF) / 0x7FFF; -#else /* RAND_MAX */ - return ((double) random()) / RAND_MAX; -#endif /* RAND_MAX */ -} - - - -static void initPointArrays (void) +static void +initPointArrays(void) { - XWindowAttributes wa; int q, w, - mx, my, /* Max screen coordinates. */ - mp, /* Max point number. */ + mx, my, /* max screen coordinates. */ + mp, /* max point number. */ s, rx, ry, marginx, marginy; double scalex, scaley; - XGetWindowAttributes(dpy, window, &wa); - mx = wa.width - 1; - my = wa.height - 1; - mp = cPoint - 1; - - aWork[0] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); - aWork[1] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); - aTmp = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); - - - /* - * Figure 0 - */ - a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); - s = cPoint / 4; - for (q = 0; q < s; q++) { - a[cFig][q].x = ((double) q / s) * mx; - a[cFig][q].y = 0; - a[cFig][s + q].x = mx; - a[cFig][s + q].y = ((double) q / s) * my; - a[cFig][2 * s + q].x = mx - ((double) q / s) * mx; - a[cFig][2 * s + q].y = my; - a[cFig][3 * s + q].x = 0; - a[cFig][3 * s + q].y = my - ((double) q / s) * my; - } - for (q = 4 * s; q < cPoint; q++) - a[cFig][q].x = a[cFig][q].y = 0; - a[cFig][mp].x = a[cFig][0].x; - a[cFig][mp].y = a[cFig][0].y; - ++cFig; - - /* - * Figure 1 - */ - a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); - for (q = 0; q < cPoint; q++) { - a[cFig][q].x = ((double) q / cPoint) * mx; - a[cFig][q].y = (1.0 - sin(((double) q / mp) * TWO_PI)) * my / 2.0; - } - ++cFig; - - /* - * Figure 2 - */ - a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); - rx = mx / 2; - ry = my / 2; - for (q = 0; q < cPoint; q++) { - a[cFig][q].x = mx / 2 + rx * sin(1 * TWO_PI * (double) q / mp); - a[cFig][q].y = my / 2 + ry * cos(3 * TWO_PI * (double) q / mp); - } - a[cFig][mp].x = a[cFig][0].x; - a[cFig][mp].y = a[cFig][0].y; - ++cFig; - - /* - * Figure 3 - */ - a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); - rx = mx / 2; - ry = my / 2; - for (q = 0; q < cPoint; q++) { - a[cFig][q].x = mx / 2 + ry * sin(3 * TWO_PI * (double) q / mp); - a[cFig][q].y = my / 2 + ry * cos(1 * TWO_PI * (double) q / mp); - } - a[cFig][mp].x = a[cFig][0].x; - a[cFig][mp].y = a[cFig][0].y; - ++cFig; - - /* - * Figure 4 - */ - a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); - rx = mx / 2; - ry = my / 2; - for (q = 0; q < cPoint; q++) { - a[cFig][q].x = mx / 2 + ry * (1 - 0.1 * frnd()) - * sin(TWO_PI * (double) q / mp); - a[cFig][q].y = my / 2 + ry * (1 - 0.1 * frnd()) - * cos(TWO_PI * (double) q / mp); - } - a[cFig][mp].x = a[cFig][0].x; - a[cFig][mp].y = a[cFig][0].y; - ++cFig; - - /* - * Figure 5 - */ - a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); - rx = mx / 2; - ry = my / 2; - for (q = 0; q < cPoint; q++) { - a[cFig][q].x = mx / 2 + ry * (0.8 - 0.2 * sin(30 * TWO_PI * q / mp)) - * sin(TWO_PI * (double) q / mp); - a[cFig][q].y = my / 2 + ry * (0.8 - 0.2 * sin(30 * TWO_PI * q / mp)) - * cos(TWO_PI * (double) q / mp); - } - a[cFig][mp].x = a[cFig][0].x; - a[cFig][mp].y = a[cFig][0].y; - ++cFig; - - /* - * Figure 6 - */ - a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); - rx = mx / 2; - ry = my / 2; - for (q = 0; q < cPoint; q++) { - a[cFig][q].x = mx / 2 + ry * sin(TWO_PI * (double) q / mp); - a[cFig][q].y = my / 2 + ry * cos(TWO_PI * (double) q / mp); - } - a[cFig][mp].x = a[cFig][0].x; - a[cFig][mp].y = a[cFig][0].y; - ++cFig; - - /* - * Figure 7 - */ - a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); - rx = mx / 2; - ry = my / 2; - for (q = 0; q < cPoint; q++) { - a[cFig][q].x = mx / 2 + rx * cos(TWO_PI * (double) q / mp); - a[cFig][q].y = my / 2 + ry * sin(TWO_PI * (double) q / mp); - } - a[cFig][mp].x = a[cFig][0].x; - a[cFig][mp].y = a[cFig][0].y; - ++cFig; - - /* - * Figure 8 - */ - a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); - for (q = 0; q < cPoint; q++) { - a[cFig][q].x = ((double) q / mp) * mx; - a[cFig][q].y = (1.0 - cos(((double) q / mp) * 3 * TWO_PI)) * my / 2.0; - } - ++cFig; - - /* - * Figure 9 - */ - a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); - rx = mx / 2; - ry = my / 2; - for (q = 0; q < cPoint; q++) { - a[cFig][q].x = mx / 2 + rx * sin(2 * TWO_PI * (double) q / mp); - a[cFig][q].y = my / 2 + ry * cos(3 * TWO_PI * (double) q / mp); - } - a[cFig][mp].x = a[cFig][0].x; - a[cFig][mp].y = a[cFig][0].y; - ++cFig; - - /* - * Figure 10 - */ - a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); - rx = mx / 2; - ry = my / 2; - for (q = 0; q < cPoint; q++) { - a[cFig][q].x = mx / 2 + ry * sin(5 * TWO_PI * (double) q / mp) - * ((double) q / mp); - a[cFig][q].y = my / 2 + ry * cos(5 * TWO_PI * (double) q / mp) - * ((double) q / mp); - } - ++cFig; - - /* - * Figure 11 - */ - a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); - rx = mx / 2; - ry = my / 2; - for (q = 0; q < cPoint; q++) { - a[cFig][q].x = mx / 2 + ry * sin(6 * TWO_PI * (double) q / mp) - * ((double) q / mp); - a[cFig][q].y = my / 2 - ry * cos(6 * TWO_PI * (double) q / mp) - * ((double) q / mp); + mx = scrWidth - 1; + my = scrHeight - 1; + mp = numPoints - 1; + + aWork[0] = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); + aWork[1] = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); + aTmp = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); + + if (figType & FT_CLOSED) { + /* rectangle */ + a[numFigs] = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); + s = numPoints / 4; + for (q = 0; q < s; q++) { + a[numFigs][q].x = ((double) q / s) * mx; + a[numFigs][q].y = 0; + a[numFigs][s + q].x = mx; + a[numFigs][s + q].y = ((double) q / s) * my; + a[numFigs][2 * s + q].x = mx - ((double) q / s) * mx; + a[numFigs][2 * s + q].y = my; + a[numFigs][3 * s + q].x = 0; + a[numFigs][3 * s + q].y = my - ((double) q / s) * my; + } + for (q = 4 * s; q < numPoints; q++) + a[numFigs][q].x = a[numFigs][q].y = 0; + a[numFigs][mp].x = a[numFigs][0].x; + a[numFigs][mp].y = a[numFigs][0].y; + ++numFigs; + + /* */ + a[numFigs] = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < numPoints; q++) { + a[numFigs][q].x = mx / 2 + rx * sin(1 * TWO_PI * (double) q / mp); + a[numFigs][q].y = my / 2 + ry * cos(3 * TWO_PI * (double) q / mp); + } + a[numFigs][mp].x = a[numFigs][0].x; + a[numFigs][mp].y = a[numFigs][0].y; + ++numFigs; + + /* */ + a[numFigs] = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < numPoints; q++) { + a[numFigs][q].x = mx / 2 + ry * sin(3 * TWO_PI * (double) q / mp); + a[numFigs][q].y = my / 2 + ry * cos(1 * TWO_PI * (double) q / mp); + } + a[numFigs][mp].x = a[numFigs][0].x; + a[numFigs][mp].y = a[numFigs][0].y; + ++numFigs; + + /* */ + a[numFigs] = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < numPoints; q++) { + a[numFigs][q].x = mx / 2 + ry + * (0.8 - 0.2 * sin(30 * TWO_PI * q / mp)) + * sin(TWO_PI * (double) q / mp); + a[numFigs][q].y = my / 2 + ry + * (0.8 - 0.2 * sin(30 * TWO_PI * q / mp)) + * cos(TWO_PI * (double) q / mp); + } + a[numFigs][mp].x = a[numFigs][0].x; + a[numFigs][mp].y = a[numFigs][0].y; + ++numFigs; + + /* */ + a[numFigs] = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < numPoints; q++) { + a[numFigs][q].x = mx / 2 + ry * sin(TWO_PI * (double) q / mp); + a[numFigs][q].y = my / 2 + ry * cos(TWO_PI * (double) q / mp); + } + a[numFigs][mp].x = a[numFigs][0].x; + a[numFigs][mp].y = a[numFigs][0].y; + ++numFigs; + + /* */ + a[numFigs] = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < numPoints; q++) { + a[numFigs][q].x = mx / 2 + rx * cos(TWO_PI * (double) q / mp); + a[numFigs][q].y = my / 2 + ry * sin(TWO_PI * (double) q / mp); + } + a[numFigs][mp].x = a[numFigs][0].x; + a[numFigs][mp].y = a[numFigs][0].y; + ++numFigs; + + /* */ + a[numFigs] = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < numPoints; q++) { + a[numFigs][q].x = mx / 2 + rx * sin(2 * TWO_PI * (double) q / mp); + a[numFigs][q].y = my / 2 + ry * cos(3 * TWO_PI * (double) q / mp); + } + a[numFigs][mp].x = a[numFigs][0].x; + a[numFigs][mp].y = a[numFigs][0].y; + ++numFigs; } - ++cFig; - - /* - * Figure 12 - */ - a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); - for (q = 0; q < cPoint; q++) { - a[cFig][q].x = ((double) q / mp) * mx; - a[cFig][q].y = (1.0 - sin(((double) q / mp) * 5 * TWO_PI)) * my / 2.0; + + if (figType & FT_OPEN) { + /* sine wave, one period */ + a[numFigs] = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); + for (q = 0; q < numPoints; q++) { + a[numFigs][q].x = ((double) q / numPoints) * mx; + a[numFigs][q].y = (1.0 - sin(((double) q / mp) * TWO_PI)) + * my / 2.0; + } + ++numFigs; + + /* */ + a[numFigs] = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); + for (q = 0; q < numPoints; q++) { + a[numFigs][q].x = ((double) q / mp) * mx; + a[numFigs][q].y = (1.0 - cos(((double) q / mp) * 3 * TWO_PI)) + * my / 2.0; + } + ++numFigs; + + /* spiral, one endpoint at bottom */ + a[numFigs] = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < numPoints; q++) { + a[numFigs][q].x = mx / 2 + ry * sin(5 * TWO_PI * (double) q / mp) + * ((double) q / mp); + a[numFigs][q].y = my / 2 + ry * cos(5 * TWO_PI * (double) q / mp) + * ((double) q / mp); + } + ++numFigs; + + /* spiral, one endpoint at top */ + a[numFigs] = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < numPoints; q++) { + a[numFigs][q].x = mx / 2 + ry * sin(6 * TWO_PI * (double) q / mp) + * ((double) q / mp); + a[numFigs][q].y = my / 2 - ry * cos(6 * TWO_PI * (double) q / mp) + * ((double) q / mp); + } + ++numFigs; + + /* */ + a[numFigs] = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); + for (q = 0; q < numPoints; q++) { + a[numFigs][q].x = ((double) q / mp) * mx; + a[numFigs][q].y = (1.0 - sin(((double) q / mp) * 5 * TWO_PI)) + * my / 2.0; + } + ++numFigs; } - ++cFig; #ifdef MARGINS - /* - * Make some space around the figures. - */ + /* make some space around the figures. */ marginx = (mx + 1) / 10; marginy = (my + 1) / 10; scalex = (double) ((mx + 1) - 2.0 * marginx) / (mx + 1.0); scaley = (double) ((my + 1) - 2.0 * marginy) / (my + 1.0); - for (q = 0; q < cFig; q++) - for (w = 0; w < cPoint; w++) { + for (q = 0; q < numFigs; q++) + for (w = 0; w < numPoints; w++) { a[q][w].x = marginx + a[q][w].x * scalex; a[q][w].y = marginy + a[q][w].y * scaley; } #endif } - - -static void createPoints (void) -{ - int q; - XPoint *pa = aCurr, *pa1 = aFrom, *pa2 = aTo; - long lg, l1g; - - - lg = 8192L * gam, l1g = 8192L * (1.0 - gam); - for (q = 0; q < cPoint; q++) { - pa->x = (short) ((l1g * pa1->x + lg * pa2->x) / 8192L); - pa->y = (short) ((l1g * pa1->y + lg * pa2->y) / 8192L); - ++pa; - ++pa1; - ++pa2; - } -} - - -static void drawImage (void) -{ - register int q; - XPoint *old0, *old1, *new0, *new1; - - /* - * Problem: update the window without too much flickering. I do - * this by handling each linesegment separately. First remove a - * line, then draw the new line. The problem is that this leaves - * small black pixels on the figure. To fix this, I draw the - * entire figure using XDrawLines() afterwards. - */ - if (aPrev) { - old0 = aPrev; - old1 = aPrev + 1; - new0 = aCurr; - new1 = aCurr + 1; - for (q = cPoint - 1; q; q--) { - XDrawLine(dpy, window, gcClear, - old0->x, old0->y, old1->x, old1->y); - XDrawLine(dpy, window, gcDraw, - new0->x, new0->y, new1->x, new1->y); - ++old0; - ++old1; - ++new0; - ++new1; - } - } - XDrawLines(dpy, window, gcDraw, aCurr, cPoint, CoordModeOrigin); - XFlush(dpy); -} - -static void initLMorph (void) +static void +initLMorph(void) { int steps; XGCValues gcv; XWindowAttributes wa; Colormap cmap; + char *ft; - cPoint = get_integer_resource("points", "Integer"); + numPoints = get_integer_resource("points", "Integer"); steps = get_integer_resource("steps", "Integer"); delay = get_integer_resource("delay", "Integer"); + ft = get_string_resource("figtype", "String"); + + if (strcmp(ft, "all") == 0) + figType = FT_ALL; + else if (strcmp(ft, "open") == 0) + figType = FT_OPEN; + else if (strcmp(ft, "closed") == 0) + figType = FT_CLOSED; + else { + fprintf(stderr, "figtype should be `all', `open' or `closed'.\n"); + figType = FT_ALL; + } if (steps <= 0) steps = (random() % 400) + 100; - delta_gam = 1.0 / steps; + deltaGamma = 1.0 / steps; XGetWindowAttributes(dpy, window, &wa); + scrWidth = wa.width; + scrHeight = wa.height; cmap = wa.colormap; gcv.foreground = get_pixel_resource("foreground", "Foreground", dpy, cmap); gcDraw = XCreateGC(dpy, window, GCForeground, &gcv); @@ -423,13 +363,14 @@ static void initLMorph (void) gcClear = XCreateGC(dpy, window, GCForeground, &gcv); XClearWindow(dpy, window); + srandom(time(NULL)); initPointArrays(); aCurr = aWork[nWork = 0]; aPrev = NULL; - gam = 2.0; - nTo = RND(cFig); + currGamma = maxGamma + 1.0; /* force creation of new figure at startup */ + nTo = RND(numFigs); - { + { /* jwz for version 2.11 */ int width = random() % 10; int style = LineSolid; int cap = (width > 1 ? CapRound : CapButt); @@ -438,45 +379,108 @@ static void initLMorph (void) XSetLineAttributes(dpy, gcDraw, width, style, cap, join); XSetLineAttributes(dpy, gcClear, width, style, cap, join); } +} + +/* 55% of execution time */ +static void +createPoints(void) +{ + int q; + XPoint *pa = aCurr, *pa1 = aFrom, *pa2 = aTo; +#ifdef USE_FLOAT + float fg, f1g; +#else + long lg, l1g; +#endif + +#ifdef USE_FLOAT + fg = currGamma; + f1g = 1.0 - currGamma; +#else + lg = 8192L * currGamma; + l1g = 8192L * (1.0 - currGamma); +#endif + for (q = numPoints; q; q--) { +#ifdef USE_FLOAT + pa->x = (short) (f1g * pa1->x + fg * pa2->x); + pa->y = (short) (f1g * pa1->y + fg * pa2->y); +#else + pa->x = (short) ((l1g * pa1->x + lg * pa2->x) / 8192L); + pa->y = (short) ((l1g * pa1->y + lg * pa2->y) / 8192L); +#endif + ++pa; + ++pa1; + ++pa2; + } +} + +/* 36% of execution time */ +static void +drawImage(void) +{ + int q; + XPoint *old0, *old1, *new0, *new1; + + /* Problem: update the window without too much flickering. I do + * this by handling each linesegment separately. First remove a + * line, then draw the new line. The problem is that this leaves + * small black pixels on the figure. To fix this, I draw the + * entire figure using XDrawLines() afterwards. */ + if (aPrev) { + old0 = aPrev; + old1 = aPrev + 1; + new0 = aCurr; + new1 = aCurr + 1; + for (q = numPoints - 1; q; q--) { + XDrawLine(dpy, window, gcClear, + old0->x, old0->y, old1->x, old1->y); + XDrawLine(dpy, window, gcDraw, + new0->x, new0->y, new1->x, new1->y); + ++old0; + ++old1; + ++new0; + ++new1; + } + } + XDrawLines(dpy, window, gcDraw, aCurr, numPoints, CoordModeOrigin); + XFlush(dpy); } -static void animateLMorph (void) +/* neglectible % of execution time */ +static void +animateLMorph(void) { - if (gam > maxGamma) { - gam = 0.0; + if (currGamma > maxGamma) { + currGamma = 0.0; if (maxGamma == 1.0) { nFrom = nTo; aFrom = a[nFrom]; } else { - memcpy(aTmp, aCurr, cPoint * sizeof(XPoint)); + memcpy(aTmp, aCurr, numPoints * sizeof(XPoint)); aFrom = aTmp; nFrom = -1; } do { - nTo = RND(cFig); + nTo = RND(numFigs); } while (nTo == nFrom); aTo = a[nTo]; if (RND(2)) { - /* - * Reverse the array to get more variation. - */ + /* reverse the array to get more variation. */ int i1, i2; XPoint p; - for (i1 = 0, i2 = cPoint - 1; i1 < cPoint / 2; i1++, i2--) { + for (i1 = 0, i2 = numPoints - 1; i1 < numPoints / 2; i1++, i2--) { p = aTo[i1]; aTo[i1] = aTo[i2]; aTo[i2] = p; } } - /* - * It may be nice to interrupt the next run. - */ - if (RND(3) > 0) - maxGamma = 0.1 + 0.7 * (RND(1001) / 1000.0); + /* occationally interrupt the next run. */ + if (RND(4) == 0) + maxGamma = 0.1 + 0.7 * (RND(1001) / 1000.0); /* partial run */ else - maxGamma = 1.0; + maxGamma = 1.0; /* full run */ } createPoints(); @@ -484,7 +488,7 @@ static void animateLMorph (void) aPrev = aCurr; aCurr = aWork[nWork ^= 1]; - gam += delta_gam; + currGamma += deltaGamma; }