1 /* truchet --- curved and straight tilings
2 * Copyright (c) 1998 Adrian Likins <adrian@gimp.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
13 /* This screensaver draws two varieties of truchet patterns, a curved one and
14 a straight one. There are lots and lots of command line options to play
17 If your running remotely or on a slow machine or slow xserver, some of the
18 settings will be way too much. The default settings should be okay though.
20 This screensaver doesnt use anything bizarre or special at all, just a few
23 A few suggested commandline combos..All these were tested on a k6-200
24 running XFree86 3.3 on a ark2000, so your mileage may vary...
26 truchet -delay 200 -no-curves
27 truchet -delay 500 -no-curves -square -no-erase
28 truchet -delay 500 -no-erase -square -erase-count 5
30 truchet -scroll -no-erase -anim-step-size 9
31 truchet -delay 200 -no-angles -min-width 36 -max-width 36
32 truchet -delay 200 -no-curves -min-width 12 -max-width 12
33 truchet -delay 200 -no-curves -min-width 36 -max-width 36 -no-erase
34 truchet -delay 100 -min-width 256 -max-width 512 -no-erase \
35 -min-linewidth 96 -root
36 truchet -min-width 64 -max-width 128 -no-erase -max-linewidth 4 \
38 truchet -min-width 64 -max-width 128 -no-erase -max-linewidth 4 \
39 -root -no-curves -delay 25
42 #include "screenhack.h"
46 static const char *truchet_defaults [] = {
60 "*scroll-overlap: 400",
67 /* options passed to this program */
68 static XrmOptionDescRec truchet_options [] = {
69 { "-min-width", ".minWidth", XrmoptionSepArg, 0 },
70 { "-max-height", ".max-Height", XrmoptionSepArg, 0 },
71 { "-max-width", ".max-Width", XrmoptionSepArg, 0 },
72 { "-min-height", ".minHeight", XrmoptionSepArg, 0 },
73 { "-max-linewidth", ".maxLineWidth", XrmoptionSepArg, 0 },
74 { "-min-linewidth", ".minLineWidth", XrmoptionSepArg, 0 },
75 { "-erase", ".erase", XrmoptionNoArg, "True" },
76 { "-no-erase", ".erase", XrmoptionNoArg, "False" },
77 { "-erase-count", ".eraseCount", XrmoptionSepArg, 0 },
78 { "-square", ".square", XrmoptionNoArg, "True" },
79 { "-not-square", ".square", XrmoptionNoArg, "False" },
80 { "-curves", ".curves", XrmoptionNoArg, "True" },
81 { "-angles", ".angles", XrmoptionNoArg, "True" },
82 { "-no-angles", ".angles", XrmoptionNoArg, "False" },
83 { "-no-curves", ".curves", XrmoptionNoArg, "False" },
84 { "-delay", ".delay", XrmoptionSepArg, 0 },
85 { "-scroll", ".scroll", XrmoptionNoArg, "True" },
86 { "-scroll-overlap", ".scroll-overlap", XrmoptionSepArg, 0 },
87 { "-anim-delay", ".anim-delay", XrmoptionSepArg, 0 },
88 { "-anim-step-size", ".anim-step-size", XrmoptionSepArg, 0 },
89 { "-randomize", ".randomize", XrmoptionNoArg, "True" },
101 XWindowAttributes xgwa;
127 static void draw_truchet(struct state *st);
128 static void draw_angles(struct state *st);
129 static void scroll_area(struct state *st, int step_size);
131 static void draw_angles(struct state *st)
135 while((st->xgwa.height+st->overlap) > cy*st->height)
137 while((st->xgwa.width+st->overlap) > cx*st->width)
142 XDrawLine(st->dpy,st->frame,st->agc,
143 (cx*st->width)+(st->width/2),
145 (cx*st->width)+(st->width),
146 (cy*st->height)+(st->height/2));
147 XDrawLine(st->dpy,st->frame,st->agc,
149 (cy*st->height)+(st->height/2),
150 (cx*st->width)+(st->width/2),
151 (cy*st->height)+(st->height));
156 XDrawLine(st->dpy,st->frame,st->agc,
157 (cx*st->width)+(st->width/2),
160 (cy*st->height)+(st->height/2));
161 XDrawLine(st->dpy,st->frame,st->agc,
162 (cx*st->width)+(st->width),
163 (cy*st->height)+(st->height/2),
164 (cx*st->width)+(st->width/2),
165 (cy*st->height)+(st->height));
175 static void draw_truchet(struct state *st)
179 while(st->xgwa.height+st->overlap > cy*st->height)
181 while(st->xgwa.width+st->overlap > cx*st->width)
186 XDrawArc(st->dpy, st->frame, st->agc,
187 ((cx*st->width)-(st->width/2)),
188 ((cy*st->height)-(st->height/2)),
192 XDrawArc(st->dpy,st->frame, st->agc,
193 ((cx*st->width)+(st->width/2)),
194 ((cy*st->height)+(st->height/2)),
203 XDrawArc(st->dpy,st->frame,st->agc,
204 ((cx*st->width)+(st->width/2)),
205 ((cy*st->height)-(st->height/2)),
210 XDrawArc(st->dpy,st->frame,st->agc,
211 ((cx*st->width)-(st->width/2)),
212 ((cy*st->height)+(st->height/2)),
226 static void scroll_area(struct state *st, int step_size)
235 offset=st->overlap/2;
236 scroll=st->overlap/4;
238 /* This runs in a loop, starting with
239 * st->scrolling = (scroll / st->anim_step_size) * 4 - 1;
240 * and going all the way down to st->scrolling = 0.
243 /* if anyone knows a good way to generate
244 * a more random scrolling motion... */
246 direction = st->scrolling / (scroll / st->anim_step_size);
247 progress = (st->scrolling % (scroll / st->anim_step_size)) * st->anim_step_size;
250 scrollcount_x = progress - scroll;
251 scrollcount_y = progress;
253 scrollcount_x = -progress;
254 scrollcount_y = progress - scroll;
258 scrollcount_x = -scrollcount_x;
259 scrollcount_y = -scrollcount_y;
262 XCopyArea(st->dpy, st->frame, st->window, st->agc,scrollcount_x+offset,scrollcount_y+offset, st->xgwa.width, st->xgwa.height, 0,0);
267 truchet_init (Display *dpy, Window window)
269 struct state *st = (struct state *) calloc (1, sizeof(*st));
274 st->maxlinewidth = get_integer_resource (st->dpy, "maxLineWidth", "Integer");
275 st->minlinewidth = get_integer_resource (st->dpy, "minLineWidth", "Integer");
276 st->minwidth = get_integer_resource (st->dpy, "minWidth", "Integer");
277 st->minheight = get_integer_resource (st->dpy, "minHeight", "Integer");
278 st->max_width = get_integer_resource (st->dpy, "max-Width", "Integer");
279 st->max_height = get_integer_resource (st->dpy, "max-Height", "Integer" );
280 st->delay = get_integer_resource (st->dpy, "delay", "Integer");
281 st->eraseCount = get_integer_resource (st->dpy, "eraseCount", "Integer");
282 st->square = get_boolean_resource (st->dpy, "square", "Boolean");
283 st->curves = get_boolean_resource (st->dpy, "curves", "Boolean");
284 st->angles = get_boolean_resource (st->dpy, "angles", "Boolean");
285 st->erase = get_boolean_resource (st->dpy, "erase", "Boolean");
286 st->scroll = get_boolean_resource (st->dpy, "scroll", "Boolean");
287 st->overlap = get_integer_resource (st->dpy, "scroll-overlap", "Integer");
288 st->anim_delay = get_integer_resource (st->dpy, "anim-delay", "Integer");
289 st->anim_step_size = get_integer_resource (st->dpy, "anim-step-size", "Integer");
291 if (get_boolean_resource(st->dpy, "randomize", "Randomize"))
293 int i = (random() % 12);
316 st->anim_step_size = 9;
320 st->minwidth = st->max_width = 36;
324 st->minwidth = st->max_width = 12;
329 st->minwidth = st->max_width = 36;
335 st->minlinewidth = 96;
341 st->maxlinewidth = 4;
347 st->maxlinewidth = 4;
355 XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
356 st->gcv.foreground = BlackPixel(st->dpy,0);
357 st->gcv.background = WhitePixel(st->dpy,0);
358 st->gcv.line_width = 25;
359 st->cmap = st->xgwa.colormap;
361 st->gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap,
362 "background", "Background");
364 st->bgc = XCreateGC (st->dpy, st->window, GCForeground, &st->gcv);
365 st->agc = XCreateGC(st->dpy, st->window, GCForeground, &st->gcv);
367 XFillRectangle(st->dpy, st->window, st->bgc, 0, 0, st->xgwa.width, st->xgwa.height);
374 XSetForeground(st->dpy, st->agc, st->gcv.background);
377 st->frame = XCreatePixmap(st->dpy,st->window, st->xgwa.width+st->overlap, st->xgwa.height+st->overlap, st->xgwa.depth);
378 XFillRectangle(st->dpy, st->frame, st->bgc, 0, 0,
379 st->xgwa.width + st->overlap,
380 st->xgwa.height + st->overlap);
386 truchet_draw (Display *dpy, Window window, void *closure)
388 struct state *st = (struct state *) closure;
393 scroll_area(st, st->anim_step_size);
394 return st->anim_delay*1000;
399 /* XXX there are probably bugs with this. */
400 /* could be...I just borrowed this code from munch */
402 st->fgc.red = random() % 65535;
403 st->fgc.green = random() % 65535;
404 st->fgc.blue = random() % 65535;
406 if (XAllocColor(st->dpy, st->cmap, &st->fgc))
408 XSetForeground(st->dpy, st->agc, st->fgc.pixel);
412 /* use white if all else fails */
413 XSetForeground(st->dpy,st->agc, st->gcv.background);
420 /* generate a random line width */
421 st->linewidth=(random()% st->maxlinewidth);
423 /* check for lower bound */
424 if(st->linewidth < st->minlinewidth)
425 st->linewidth = st->minlinewidth;
427 /* try to get an odd linewidth as it seem to work a little better */
431 /* grab a random height and width */
432 st->width=(random()%st->max_width);
433 st->height=(random()%st->max_height);
435 /* make sure we dont get a 0 height or width */
436 if(st->width == 0 || st->height == 0)
438 st->height=st->max_height;
439 st->width=st->max_width;
443 /* check for min height and width */
444 if(st->height < st->minheight)
446 st->height=st->minheight;
448 if(st->width < st->minwidth)
450 st->width=st->minwidth;
453 /* if tiles need to be square, fix it... */
455 st->height=st->width;
457 /* check for sane aspect ratios */
458 if((st->width/st->height) > MAXRATIO)
459 st->height=st->width;
460 if((st->height/st->width) > MAXRATIO)
461 st->width=st->height;
463 /* to avoid linewidths of zero */
464 if(st->linewidth == 0 || st->linewidth < st->minlinewidth)
465 st->linewidth = st->minlinewidth;
467 /* try to keep from getting line widths that would be too big */
468 if(st->linewidth > 0 && st->linewidth >= (st->height/5))
469 st->linewidth = st->height/5;
471 XSetLineAttributes(st->dpy, st->agc, st->linewidth, LineSolid, CapRound, JoinRound);
473 if(st->erase || (st->count >= st->eraseCount))
475 /* XClearWindow(dpy,window); */
476 XFillRectangle(st->dpy, st->frame, st->bgc, 0, 0, st->xgwa.width+st->overlap, st->xgwa.height+st->overlap);
483 /* do the fun stuff...*/
484 if(st->curves && st->angles)
491 else if(st->curves && !st->angles)
493 else if(!st->curves && st->angles)
501 st->scrolling = ((st->overlap / 4) / st->anim_step_size) * 4;
505 XCopyArea(st->dpy,st->frame,st->window,st->agc,0,0,st->xgwa.width,st->xgwa.height,0,0);
511 truchet_reshape (Display *dpy, Window window, void *closure,
512 unsigned int w, unsigned int h)
514 struct state *st = (struct state *) closure;
517 XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
521 truchet_event (Display *dpy, Window window, void *closure, XEvent *event)
527 truchet_free (Display *dpy, Window window, void *closure)
532 XSCREENSAVER_MODULE ("Truchet", truchet)