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",
65 "*ignoreRotation: True",
70 /* options passed to this program */
71 static XrmOptionDescRec truchet_options [] = {
72 { "-min-width", ".minWidth", XrmoptionSepArg, 0 },
73 { "-max-height", ".max-Height", XrmoptionSepArg, 0 },
74 { "-max-width", ".max-Width", XrmoptionSepArg, 0 },
75 { "-min-height", ".minHeight", XrmoptionSepArg, 0 },
76 { "-max-linewidth", ".maxLineWidth", XrmoptionSepArg, 0 },
77 { "-min-linewidth", ".minLineWidth", XrmoptionSepArg, 0 },
78 { "-erase", ".erase", XrmoptionNoArg, "True" },
79 { "-no-erase", ".erase", XrmoptionNoArg, "False" },
80 { "-erase-count", ".eraseCount", XrmoptionSepArg, 0 },
81 { "-square", ".square", XrmoptionNoArg, "True" },
82 { "-not-square", ".square", XrmoptionNoArg, "False" },
83 { "-curves", ".curves", XrmoptionNoArg, "True" },
84 { "-angles", ".angles", XrmoptionNoArg, "True" },
85 { "-no-angles", ".angles", XrmoptionNoArg, "False" },
86 { "-no-curves", ".curves", XrmoptionNoArg, "False" },
87 { "-delay", ".delay", XrmoptionSepArg, 0 },
88 { "-scroll", ".scroll", XrmoptionNoArg, "True" },
89 { "-scroll-overlap", ".scroll-overlap", XrmoptionSepArg, 0 },
90 { "-anim-delay", ".anim-delay", XrmoptionSepArg, 0 },
91 { "-anim-step-size", ".anim-step-size", XrmoptionSepArg, 0 },
92 { "-randomize", ".randomize", XrmoptionNoArg, "True" },
104 XWindowAttributes xgwa;
130 static void draw_truchet(struct state *st);
131 static void draw_angles(struct state *st);
132 static void scroll_area(struct state *st, int step_size);
134 static void draw_angles(struct state *st)
138 while((st->xgwa.height+st->overlap) > cy*st->height)
140 while((st->xgwa.width+st->overlap) > cx*st->width)
145 XDrawLine(st->dpy,st->frame,st->agc,
146 (cx*st->width)+(st->width/2),
148 (cx*st->width)+(st->width),
149 (cy*st->height)+(st->height/2));
150 XDrawLine(st->dpy,st->frame,st->agc,
152 (cy*st->height)+(st->height/2),
153 (cx*st->width)+(st->width/2),
154 (cy*st->height)+(st->height));
159 XDrawLine(st->dpy,st->frame,st->agc,
160 (cx*st->width)+(st->width/2),
163 (cy*st->height)+(st->height/2));
164 XDrawLine(st->dpy,st->frame,st->agc,
165 (cx*st->width)+(st->width),
166 (cy*st->height)+(st->height/2),
167 (cx*st->width)+(st->width/2),
168 (cy*st->height)+(st->height));
178 static void draw_truchet(struct state *st)
182 while(st->xgwa.height+st->overlap > cy*st->height)
184 while(st->xgwa.width+st->overlap > cx*st->width)
189 XDrawArc(st->dpy, st->frame, st->agc,
190 ((cx*st->width)-(st->width/2)),
191 ((cy*st->height)-(st->height/2)),
195 XDrawArc(st->dpy,st->frame, st->agc,
196 ((cx*st->width)+(st->width/2)),
197 ((cy*st->height)+(st->height/2)),
206 XDrawArc(st->dpy,st->frame,st->agc,
207 ((cx*st->width)+(st->width/2)),
208 ((cy*st->height)-(st->height/2)),
213 XDrawArc(st->dpy,st->frame,st->agc,
214 ((cx*st->width)-(st->width/2)),
215 ((cy*st->height)+(st->height/2)),
229 static void scroll_area(struct state *st, int step_size)
238 offset=st->overlap/2;
239 scroll=st->overlap/4;
241 /* This runs in a loop, starting with
242 * st->scrolling = (scroll / st->anim_step_size) * 4 - 1;
243 * and going all the way down to st->scrolling = 0.
246 /* if anyone knows a good way to generate
247 * a more random scrolling motion... */
249 direction = st->scrolling / (scroll / st->anim_step_size);
250 progress = (st->scrolling % (scroll / st->anim_step_size)) * st->anim_step_size;
253 scrollcount_x = progress - scroll;
254 scrollcount_y = progress;
256 scrollcount_x = -progress;
257 scrollcount_y = progress - scroll;
261 scrollcount_x = -scrollcount_x;
262 scrollcount_y = -scrollcount_y;
265 XCopyArea(st->dpy, st->frame, st->window, st->agc,scrollcount_x+offset,scrollcount_y+offset, st->xgwa.width, st->xgwa.height, 0,0);
270 truchet_init (Display *dpy, Window window)
272 struct state *st = (struct state *) calloc (1, sizeof(*st));
277 st->maxlinewidth = get_integer_resource (st->dpy, "maxLineWidth", "Integer");
278 st->minlinewidth = get_integer_resource (st->dpy, "minLineWidth", "Integer");
279 st->minwidth = get_integer_resource (st->dpy, "minWidth", "Integer");
280 st->minheight = get_integer_resource (st->dpy, "minHeight", "Integer");
281 st->max_width = get_integer_resource (st->dpy, "max-Width", "Integer");
282 st->max_height = get_integer_resource (st->dpy, "max-Height", "Integer" );
283 st->delay = get_integer_resource (st->dpy, "delay", "Integer");
284 st->eraseCount = get_integer_resource (st->dpy, "eraseCount", "Integer");
285 st->square = get_boolean_resource (st->dpy, "square", "Boolean");
286 st->curves = get_boolean_resource (st->dpy, "curves", "Boolean");
287 st->angles = get_boolean_resource (st->dpy, "angles", "Boolean");
288 st->erase = get_boolean_resource (st->dpy, "erase", "Boolean");
289 st->scroll = get_boolean_resource (st->dpy, "scroll", "Boolean");
290 st->overlap = get_integer_resource (st->dpy, "scroll-overlap", "Integer");
291 st->anim_delay = get_integer_resource (st->dpy, "anim-delay", "Integer");
292 st->anim_step_size = get_integer_resource (st->dpy, "anim-step-size", "Integer");
294 if (get_boolean_resource(st->dpy, "randomize", "Randomize"))
296 int i = (random() % 12);
319 st->anim_step_size = 9;
323 st->minwidth = st->max_width = 36;
327 st->minwidth = st->max_width = 12;
332 st->minwidth = st->max_width = 36;
338 st->minlinewidth = 96;
344 st->maxlinewidth = 4;
350 st->maxlinewidth = 4;
358 XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
359 st->gcv.foreground = BlackPixel(st->dpy,0);
360 st->gcv.background = WhitePixel(st->dpy,0);
361 st->gcv.line_width = 25;
362 st->cmap = st->xgwa.colormap;
364 st->gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap,
365 "background", "Background");
367 st->bgc = XCreateGC (st->dpy, st->window, GCForeground, &st->gcv);
368 st->agc = XCreateGC(st->dpy, st->window, GCForeground, &st->gcv);
370 XFillRectangle(st->dpy, st->window, st->bgc, 0, 0, st->xgwa.width, st->xgwa.height);
377 XSetForeground(st->dpy, st->agc, st->gcv.background);
380 st->frame = XCreatePixmap(st->dpy,st->window, st->xgwa.width+st->overlap, st->xgwa.height+st->overlap, st->xgwa.depth);
381 XFillRectangle(st->dpy, st->frame, st->bgc, 0, 0,
382 st->xgwa.width + st->overlap,
383 st->xgwa.height + st->overlap);
389 truchet_draw (Display *dpy, Window window, void *closure)
391 struct state *st = (struct state *) closure;
396 scroll_area(st, st->anim_step_size);
397 return st->anim_delay*1000;
402 /* XXX there are probably bugs with this. */
403 /* could be...I just borrowed this code from munch */
405 st->fgc.red = random() % 65535;
406 st->fgc.green = random() % 65535;
407 st->fgc.blue = random() % 65535;
409 if (XAllocColor(st->dpy, st->cmap, &st->fgc))
411 XSetForeground(st->dpy, st->agc, st->fgc.pixel);
415 /* use white if all else fails */
416 XSetForeground(st->dpy,st->agc, st->gcv.background);
423 /* generate a random line width */
424 st->linewidth=(random()% st->maxlinewidth);
426 /* check for lower bound */
427 if(st->linewidth < st->minlinewidth)
428 st->linewidth = st->minlinewidth;
430 /* try to get an odd linewidth as it seem to work a little better */
434 /* grab a random height and width */
435 st->width=(random()%st->max_width);
436 st->height=(random()%st->max_height);
438 /* make sure we dont get a 0 height or width */
439 if(st->width == 0 || st->height == 0)
441 st->height=st->max_height;
442 st->width=st->max_width;
446 /* check for min height and width */
447 if(st->height < st->minheight)
449 st->height=st->minheight;
451 if(st->width < st->minwidth)
453 st->width=st->minwidth;
456 /* if tiles need to be square, fix it... */
458 st->height=st->width;
460 /* check for sane aspect ratios */
461 if((st->width/st->height) > MAXRATIO)
462 st->height=st->width;
463 if((st->height/st->width) > MAXRATIO)
464 st->width=st->height;
466 /* to avoid linewidths of zero */
467 if(st->linewidth == 0 || st->linewidth < st->minlinewidth)
468 st->linewidth = st->minlinewidth;
470 /* try to keep from getting line widths that would be too big */
471 if(st->linewidth > 0 && st->linewidth >= (st->height/5))
472 st->linewidth = st->height/5;
474 XSetLineAttributes(st->dpy, st->agc, st->linewidth, LineSolid, CapRound, JoinRound);
476 if(st->erase || (st->count >= st->eraseCount))
478 /* XClearWindow(dpy,window); */
479 XFillRectangle(st->dpy, st->frame, st->bgc, 0, 0, st->xgwa.width+st->overlap, st->xgwa.height+st->overlap);
486 /* do the fun stuff...*/
487 if(st->curves && st->angles)
494 else if(st->curves && !st->angles)
496 else if(!st->curves && st->angles)
504 st->scrolling = ((st->overlap / 4) / st->anim_step_size) * 4;
508 XCopyArea(st->dpy,st->frame,st->window,st->agc,0,0,st->xgwa.width,st->xgwa.height,0,0);
514 truchet_reshape (Display *dpy, Window window, void *closure,
515 unsigned int w, unsigned int h)
517 struct state *st = (struct state *) closure;
520 XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
524 truchet_event (Display *dpy, Window window, void *closure, XEvent *event)
530 truchet_free (Display *dpy, Window window, void *closure)
535 XSCREENSAVER_MODULE ("Truchet", truchet)