+++ /dev/null
-/* cynosure --- draw some rectangles
- *
- * 01-aug-96: written in Java by ozymandias G desiderata <ogd@organic.com>
- * 25-dec-97: ported to C and XScreenSaver by Jamie Zawinski <jwz@jwz.org>
- *
- * Original version:
- * http://www.organic.com/staff/ogd/java/cynosure.html
- * http://www.organic.com/staff/ogd/java/source/cynosure/Cynosure-java.txt
- *
- * Original comments and copyright:
- *
- * Cynosure.java
- * A Java implementation of Stephen Linhart's Cynosure screen-saver as a
- * drop-in class.
- *
- * Header: /home/ogd/lib/cvs/aoaioxxysz/graphics/Cynosure.java,v 1.2 1996/08/02 02:41:21 ogd Exp
- *
- * ozymandias G desiderata <ogd@organic.com>
- * Thu Aug 1 1996
- *
- * COPYRIGHT NOTICE
- *
- * Copyright 1996 ozymandias G desiderata. Title, ownership rights, and
- * intellectual property rights in and to this software remain with
- * ozymandias G desiderata. This software may be copied, modified,
- * or used as long as this copyright is retained. Use this code at your
- * own risk.
- *
- * Revision: 1.2
- *
- * Log: Cynosure.java,v
- * Revision 1.2 1996/08/02 02:41:21 ogd
- * Added a few more comments, fixed messed-up header.
- *
- * Revision 1.1.1.1 1996/08/02 02:30:45 ogd
- * First version
- */
-
-#include "screenhack.h"
-static Display *dpy;
-static Window window;
-static XColor *colors;
-static int ncolors;
-static int fg_pixel, bg_pixel;
-static GC fg_gc, bg_gc, shadow_gc;
-
-static void paint(void);
-static int genNewColor(void);
-static int genConstrainedColor(int base, int tweak);
-static int c_tweak(int base, int tweak);
-
-/**
- * The current color that is being tweaked to create the
- * rectangles.
- **/
-static int curColor;
-
-/**
- * A variable used for the progression of the colors (yes, I know
- * that's a lame explanation, but if your read the source, it should
- * become obvious what I'm doing with this variable).
- **/
-static int curBase;
-
-/**
- * The width of the right and bottom edges of the rectangles.
- **/
-static int shadowWidth;
-
-/* The offset of the dropshadow beneath the rectangles. */
-static int elevation;
-
-/**
- * The approximate amount of time that will elapse before the base
- * color is permanently changed.
- *
- * @see #tweak
- **/
-static int sway;
-
-/**
- * The counter of time left until the base color value used. This class
- * variable is necessary because Java doesn't support static method
- * variables (grr grr).
- **/
-static int timeLeft;
-
-/**
- * The amount by which the color of the polygons drawn will vary.
- *
- * @see #sway;
- **/
-static int tweak;
-
-/**
- * The smallest size for an individual cell.
- **/
-#define MINCELLSIZE 16
-
-/**
- * The narrowest a rectangle can be.
- **/
-#define MINRECTSIZE 6
-
-/**
- * The size of the grid that the rectangles are placed within.
- **/
-static int gridSize;
-
-/**
- * Every so often genNewColor() generates a completely random
- * color. This variable sets how frequently that happens. It's
- * currently set to happen 1% of the time.
- *
- * @see #genNewColor
- **/
-#define THRESHOLD 100 /*0.01*/
-
-
-char *progclass = "Cynosure";
-char *defaults [] = {
- ".background: black",
- ".foreground: white",
- "*delay: 500000",
- "*colors: 128",
- "*iterations: 100",
- "*shadowWidth: 2",
- "*elevation: 5",
- "*sway: 30",
- "*tweak: 20",
- "*gridSize: 12",
- 0
-};
-
-XrmOptionDescRec options [] = {
- { "-delay", ".delay", XrmoptionSepArg, 0 },
- { "-ncolors", ".colors", XrmoptionSepArg, 0 },
- { "-iterations", ".iterations", XrmoptionSepArg, 0 },
- { 0, 0, 0, 0 }
-};
-
-
-void screenhack(Display *d, Window w)
-{
- XWindowAttributes xgwa;
- XGCValues gcv;
- int delay;
- int i, iterations;
-
- dpy = d;
- window = w;
-
- curColor = 0;
- curBase = curColor;
- shadowWidth = get_integer_resource ("shadowWidth", "Integer");
- elevation = get_integer_resource ("elevation", "Integer");
- sway = get_integer_resource ("sway", "Integer");
- tweak = get_integer_resource ("tweak", "Integer");
- gridSize = get_integer_resource ("gridSize", "Integer");
- timeLeft = 0;
-
- XGetWindowAttributes (dpy, window, &xgwa);
-
- ncolors = get_integer_resource ("colors", "Colors");
- if (ncolors < 2) ncolors = 2;
- if (ncolors <= 2) mono_p = True;
-
- if (mono_p)
- colors = 0;
- else
- colors = (XColor *) malloc(sizeof(*colors) * (ncolors+1));
-
- if (mono_p)
- ;
- else {
- make_smooth_colormap (dpy, xgwa.visual, xgwa.colormap, colors, &ncolors,
- True, 0, True);
- if (ncolors <= 2) {
- mono_p = True;
- ncolors = 2;
- if (colors) free(colors);
- colors = 0;
- }
- }
-
- bg_pixel = get_pixel_resource("background", "Background", dpy,
- xgwa.colormap);
- fg_pixel = get_pixel_resource("foreground", "Foreground", dpy,
- xgwa.colormap);
-
- gcv.foreground = fg_pixel;
- fg_gc = XCreateGC(dpy, window, GCForeground, &gcv);
- gcv.foreground = bg_pixel;
- bg_gc = XCreateGC(dpy, window, GCForeground, &gcv);
-
- gcv.fill_style = FillStippled;
- gcv.stipple = XCreateBitmapFromData(dpy, window, "\125\252", 8, 2);
- shadow_gc = XCreateGC(dpy, window, GCForeground|GCFillStyle|GCStipple, &gcv);
- XFreePixmap(dpy, gcv.stipple);
-
- delay = get_integer_resource ("delay", "Delay");
- iterations = get_integer_resource ("iterations", "Iterations");
-
- i = 0;
- while (1)
- {
- if (iterations > 0 && ++i >= iterations)
- {
- i = 0;
- if (!mono_p)
- XSetWindowBackground(dpy, window,
- colors[random() % ncolors].pixel);
- XClearWindow(dpy, window);
- }
- paint();
- XSync(dpy, False);
- screenhack_handle_events (dpy);
- if (delay)
- usleep(delay);
- }
-}
-
-/**
- * paint adds a new layer of multicolored rectangles within a grid of
- * randomly generated size. Each row of rectangles is the same color,
- * but colors vary slightly from row to row. Each rectangle is placed
- * within a regularly-sized cell, but each rectangle is sized and
- * placed randomly within that cell.
- *
- * @param g the Graphics coordinate in which to draw
- * @see #genNewColor
- **/
-static void paint(void)
-{
- int i;
- int cellsWide, cellsHigh, cellWidth, cellHeight;
- static int width, height;
- static int size_check = 1;
-
- if (--size_check <= 0)
- {
- XWindowAttributes xgwa;
- XGetWindowAttributes (dpy, window, &xgwa);
- width = xgwa.width;
- height = xgwa.height;
- size_check = 1000;
- }
-
- /* How many cells wide the grid is (equal to gridSize +/- (gridSize / 2))
- */
- cellsWide = c_tweak(gridSize, gridSize / 2);
- /* How many cells high the grid is (equal to gridSize +/- (gridSize / 2))
- */
- cellsHigh = c_tweak(gridSize, gridSize / 2);
- /* How wide each cell in the grid is */
- cellWidth = width / cellsWide;
- /* How tall each cell in the grid is */
- cellHeight = height / cellsHigh;
-
- /* Ensure that each cell is above a certain minimum size */
-
- if (cellWidth < MINCELLSIZE) {
- cellWidth = MINCELLSIZE;
- cellsWide = width / cellWidth;
- }
-
- if (cellHeight < MINCELLSIZE) {
- cellHeight = MINCELLSIZE;
- cellsHigh = width / cellWidth;
- }
-
- /* fill the grid with randomly-generated cells */
- for(i = 0; i < cellsHigh; i++) {
- int j;
-
- /* Each row is a different color, randomly generated (but constrained) */
- if (!mono_p)
- {
- int c = genNewColor();
- XSetForeground(dpy, fg_gc, colors[c].pixel);
- }
-
- for(j = 0; j < cellsWide; j++) {
- int curWidth, curHeight, curX, curY;
-
- /* Generate a random height for a rectangle and make sure that */
- /* it's above a certain minimum size */
- curHeight = random() % (cellHeight - shadowWidth);
- if (curHeight < MINRECTSIZE)
- curHeight = MINRECTSIZE;
- /* Generate a random width for a rectangle and make sure that
- it's above a certain minimum size */
- curWidth = random() % (cellWidth - shadowWidth);
- if (curWidth < MINRECTSIZE)
- curWidth = MINRECTSIZE;
- /* Figure out a random place to locate the rectangle within the
- cell */
- curY = (i * cellHeight) + (random() % ((cellHeight - curHeight) -
- shadowWidth));
- curX = (j * cellWidth) + (random() % ((cellWidth - curWidth) -
- shadowWidth));
-
- /* Draw the shadow */
- if (elevation > 0)
- XFillRectangle(dpy, window, shadow_gc,
- curX + elevation, curY + elevation,
- curWidth, curHeight);
-
- /* Draw the edge */
- if (shadowWidth > 0)
- XFillRectangle(dpy, window, bg_gc,
- curX + shadowWidth, curY + shadowWidth,
- curWidth, curHeight);
-
- XFillRectangle(dpy, window, fg_gc, curX, curY, curWidth, curHeight);
-
- /* Draw a 1-pixel black border around the rectangle */
- XDrawRectangle(dpy, window, bg_gc, curX, curY, curWidth, curHeight);
- }
-
- }
-}
-
-
-/**
- * genNewColor returns a new color, gradually mutating the colors and
- * occasionally returning a totally random color, just for variety.
- *
- * @return the new color
- **/
-static int genNewColor(void)
-{
- /* These lines handle "sway", or the gradual random changing of */
- /* colors. After genNewColor() has been called a given number of */
- /* times (specified by a random permutation of the tweak variable), */
- /* take whatever color has been most recently randomly generated and */
- /* make it the new base color. */
- if (timeLeft == 0) {
- timeLeft = c_tweak(sway, sway / 3);
- curColor = curBase;
- } else {
- timeLeft--;
- }
-
- /* If a randomly generated number is less than the threshold value,
- produce a "sport" color value that is completely unrelated to the
- current palette. */
- if (0 == (random() % THRESHOLD)) {
- return (random() % ncolors);
- } else {
- curBase = genConstrainedColor(curColor, tweak);
- return curBase;
- }
-
-}
-
-/**
- * genConstrainedColor creates a random new color within a certain
- * range of an existing color. Right now this works with RGB color
- * values, but a future version of the program will most likely use HSV
- * colors, which should generate a more pleasing progression of values.
- *
- * @param base the color on which the new color will be based
- * @param tweak the amount that the new color can be tweaked
- * @return a new constrained color
- * @see #genNewColor
- **/
-static int genConstrainedColor(int base, int tweak)
-{
- int i = 1 + (random() % tweak);
- if (random() & 1)
- i = -i;
- i = (base + i) % ncolors;
- while (i < 0)
- i += ncolors;
- return i;
-}
-
-/**
- * Utility function to generate a tweaked color value
- *
- * @param base the byte value on which the color is based
- * @param tweak the amount the value will be skewed
- * @see #tweak
- * @return the tweaked byte
- **/
-static int c_tweak(int base, int tweak)
-{
- int ranTweak = (random() % (2 * tweak));
- int n = (base + (ranTweak - tweak));
- if (n < 0) n = -n;
- return (n < 255 ? n : 255);
-}