+/* I first saw something like this, albeit in reverse, in an early Tetris
+ implementation for the Mac.
+ -- Torbjörn Andersson <torbjorn@dev.eurotime.se>
+ */
+static void
+slide_lines (Display *dpy, Window window, GC gc,
+ int width, int height, int total_msecs)
+{
+ int max = width;
+ int dy = MAX (10, height/40);
+
+ int oi = 0;
+ unsigned long start_tick = millitime();
+ unsigned long end_tick = start_tick + total_msecs;
+ unsigned long tick = start_tick;
+ int hits = 0;
+ int nonhits = 0;
+
+ while (tick < end_tick)
+ {
+ int i = (max * (tick - start_tick)) / (end_tick - start_tick);
+
+ if (i == oi)
+ {
+ usleep (LITTLE_NAP);
+ nonhits++;
+ }
+ else
+ {
+ int y;
+ int tick = 0;
+ int from1 = oi;
+ int to1 = i;
+ int w = width-to1;
+ int from2 = width - oi - w;
+ int to2 = width - i - w;
+
+ for (y = 0; y < height; y += dy)
+ {
+ if (++tick & 1)
+ {
+ XCopyArea (dpy, window, window, gc, from1, y, w, dy, to1, y);
+ XFillRectangle (dpy, window, gc, from1, y, to1-from1, dy);
+ }
+ else
+ {
+ XCopyArea (dpy, window, window, gc, from2, y, w, dy, to2, y);
+ XFillRectangle (dpy, window, gc, from2+w, y, to2-from2, dy);
+ }
+ }
+
+ hits++;
+ XSync (dpy, False);
+ }
+
+ oi = i;
+ tick = millitime();
+ }
+}
+
+
+/* from Frederick Roeber <roeber@xigo.com> */
+static void
+losira (Display * dpy, Window window, GC gc,
+ int width, int height, int total_msecs)
+{
+ XGCValues gcv;
+ XWindowAttributes wa;
+ XColor white;
+ GC white_gc;
+ XArc arc[2][8];
+ double xx[8], yy[8], dx[8], dy[8];
+
+ int i;
+ int oi = 0;
+
+ int max = width/2;
+ int max_off = MAX(1, max / 12);
+
+ int msecs1 = (0.55 * total_msecs);
+ int msecs2 = (0.30 * total_msecs);
+ int msecs3 = (0.15 * total_msecs);
+
+ unsigned long start_tick = millitime();
+ unsigned long end_tick = start_tick + msecs1;
+ unsigned long tick = start_tick;
+ int hits = 0;
+ int nonhits = 0;
+
+ XGetWindowAttributes(dpy, window, &wa);
+ white.flags = DoRed|DoGreen|DoBlue;
+ white.red = white.green = white.blue = 65535;
+ XAllocColor(dpy, wa.colormap, &white);
+ gcv.foreground = white.pixel;
+ white_gc = XCreateGC(dpy, window, GCForeground, &gcv);
+
+ /* Squeeze in from the sides */
+ while (tick < end_tick)
+ {
+ int i = (max * (tick - start_tick)) / (end_tick - start_tick);
+
+ if (i == oi)
+ {
+ usleep (LITTLE_NAP);
+ nonhits++;
+ }
+ else
+ {
+ int off = (max_off * (tick - start_tick)) / (end_tick - start_tick);
+
+ int from1 = oi;
+ int to1 = i;
+ int w = max - to1 - off/2 + 1;
+ int from2 = max+(to1-from1)+off/2;
+ int to2 = max+off/2;
+
+ if (w < 0)
+ break;
+
+ XCopyArea (dpy, window, window, gc, from1, 0, w, height, to1, 0);
+ XCopyArea (dpy, window, window, gc, from2, 0, w, height, to2, 0);
+ XFillRectangle (dpy, window, gc, from1, 0, (to1-from1), height);
+ XFillRectangle (dpy, window, gc, to2+w, 0, from2+w, height);
+ XFillRectangle (dpy, window, white_gc, max-off/2, 0, off, height);
+ hits++;
+ XSync(dpy, False);
+ }
+
+ oi = i;
+ tick = millitime();
+ }
+
+
+ XFillRectangle(dpy, window, white_gc, max-max_off/2, 0, max_off, height);
+
+ /* Cap the top and bottom of the line */
+ XFillRectangle(dpy, window, gc, max-max_off/2, 0, max_off, max_off/2);
+ XFillRectangle(dpy, window, gc, max-max_off/2, height-max_off/2,
+ max_off, max_off/2);
+ XFillArc(dpy, window, white_gc, max-max_off/2-1, 0,
+ max_off-1, max_off-1, 0, 180*64);
+ XFillArc(dpy, window, white_gc, max-max_off/2-1, height-max_off,
+ max_off-1, max_off-1,
+ 180*64, 360*64);
+
+ XFillRectangle(dpy, window, gc, 0, 0, max-max_off/2, height);
+ XFillRectangle(dpy, window, gc, max+max_off/2-1, 0, max-max_off/2, height);
+ XSync(dpy, False);
+
+ /* Collapse vertically */
+ start_tick = millitime();
+ end_tick = start_tick + msecs2;
+ tick = start_tick;
+
+ max = height/2;
+ oi = 0;
+ while (tick < end_tick)
+ {
+ int i = (max * (tick - start_tick)) / (end_tick - start_tick);
+ int x = (width-max_off)/2;
+ int w = max_off;
+
+ if (i == oi)
+ {
+ usleep (LITTLE_NAP);
+ nonhits++;
+ }
+ else
+ {
+ int off = (max_off * (tick - start_tick)) / (end_tick - start_tick);
+
+ int from1 = oi;
+ int to1 = i;
+ int h = max - to1 - off/2;
+ int from2 = max+(to1-from1)+off/2;
+ int to2 = max+off/2;
+
+ if (h < max_off/2)
+ break;
+
+ XCopyArea (dpy, window, window, gc, x, from1, w, h, x, to1);
+ XCopyArea (dpy, window, window, gc, x, from2, w, h, x, to2);
+ XFillRectangle(dpy, window, gc, x, from1, w, (to1 - from1));
+ XFillRectangle(dpy, window, gc, x, to2+h, w, (to2 - from2));
+ hits++;
+ XSync(dpy, False);
+ }
+
+ oi = i;
+ tick = millitime();
+ }
+
+ /* "This is Sci-Fi" */
+ for( i = 0; i < 8; i++ ) {
+ arc[0][i].width = arc[0][i].height = max_off;
+ arc[1][i].width = arc[1][i].height = max_off;
+ arc[0][i].x = arc[1][i].x = width/2;
+ arc[0][i].y = arc[1][i].y = height/2;
+ xx[i] = (double)(width/2) - max_off/2;
+ yy[i] = (double)(height/2) - max_off/2;
+ }
+
+ arc[0][0].angle1 = arc[1][0].angle1 = 0*64; arc[0][0].angle2 = arc[1][0].angle2 = 45*64;
+ arc[0][1].angle1 = arc[1][1].angle1 = 45*64; arc[0][1].angle2 = arc[1][1].angle2 = 45*64;
+ arc[0][2].angle1 = arc[1][2].angle1 = 90*64; arc[0][2].angle2 = arc[1][2].angle2 = 45*64;
+ arc[0][3].angle1 = arc[1][3].angle1 = 135*64; arc[0][3].angle2 = arc[1][3].angle2 = 45*64;
+ arc[0][4].angle1 = arc[1][4].angle1 = 180*64; arc[0][4].angle2 = arc[1][4].angle2 = 45*64;
+ arc[0][5].angle1 = arc[1][5].angle1 = 225*64; arc[0][5].angle2 = arc[1][5].angle2 = 45*64;
+ arc[0][6].angle1 = arc[1][6].angle1 = 270*64; arc[0][6].angle2 = arc[1][6].angle2 = 45*64;
+ arc[0][7].angle1 = arc[1][7].angle1 = 315*64; arc[0][7].angle2 = arc[1][7].angle2 = 45*64;
+
+ for( i = 0; i < 8; i++ ) {
+ dx[i] = cos((i*45 + 22.5)/360 * 2*M_PI);
+ dy[i] = -sin((i*45 + 22.5)/360 * 2*M_PI);
+ }
+
+ gcv.line_width = 3;
+ XChangeGC(dpy, gc, GCLineWidth, &gcv);
+
+ XClearWindow (dpy, window);
+ XFillArc(dpy, window, white_gc,
+ width/2-max_off/2-1, height/2-max_off/2-1,
+ max_off-1, max_off-1,
+ 0, 360*64);
+ XDrawLine(dpy, window, gc, 0, height/2-1, width, height/2-1);
+ XDrawLine(dpy, window, gc, width/2-1, 0, width/2-1, height);
+ XDrawLine(dpy, window, gc, width/2-1-max_off, height/2-1-max_off,
+ width/2+max_off, height/2+max_off);
+ XDrawLine(dpy, window, gc, width/2+max_off, height/2-1-max_off,
+ width/2-1-max_off, height/2+max_off);
+
+ XSync(dpy, False);
+
+
+ /* Fan out */
+ start_tick = millitime();
+ end_tick = start_tick + msecs3;
+ tick = start_tick;
+ oi = 0;
+ while (tick < end_tick)
+ {
+ int i = (max_off * (tick - start_tick)) / (end_tick - start_tick);
+
+ if (i == oi)
+ {
+ usleep (LITTLE_NAP);
+ nonhits++;
+ }
+ else
+ {
+ int j;
+ for (j = 0; j < 8; j++)
+ {
+ xx[j] += 2*dx[j];
+ yy[j] += 2*dy[j];
+ arc[(i+1)%2][j].x = xx[j];
+ arc[(i+1)%2][j].y = yy[j];
+ }
+
+ XFillRectangle (dpy, window, gc,
+ (width-max_off*5)/2, (height-max_off*5)/2,
+ max_off*5, max_off*5);
+ XFillArcs(dpy, window, white_gc, arc[(i+1)%2], 8);
+ XSync(dpy, False);
+ hits++;
+ }
+
+ oi = i;
+ tick = millitime();
+ }
+
+ XSync (dpy, False);
+
+ /*XFreeColors(dpy, wa.colormap, &white.pixel, 1, 0);*/
+ XFreeGC(dpy, white_gc);
+}
+
+