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);
383 truchet_draw (Display *dpy, Window window, void *closure)
385 struct state *st = (struct state *) closure;
390 scroll_area(st, st->anim_step_size);
391 return st->anim_delay*1000;
396 /* XXX there are probably bugs with this. */
397 /* could be...I just borrowed this code from munch */
399 st->fgc.red = random() % 65535;
400 st->fgc.green = random() % 65535;
401 st->fgc.blue = random() % 65535;
403 if (XAllocColor(st->dpy, st->cmap, &st->fgc))
405 XSetForeground(st->dpy, st->agc, st->fgc.pixel);
409 /* use white if all else fails */
410 XSetForeground(st->dpy,st->agc, st->gcv.background);
417 /* generate a random line width */
418 st->linewidth=(random()% st->maxlinewidth);
420 /* check for lower bound */
421 if(st->linewidth < st->minlinewidth)
422 st->linewidth = st->minlinewidth;
424 /* try to get an odd linewidth as it seem to work a little better */
428 /* grab a random height and width */
429 st->width=(random()%st->max_width);
430 st->height=(random()%st->max_height);
432 /* make sure we dont get a 0 height or width */
433 if(st->width == 0 || st->height == 0)
435 st->height=st->max_height;
436 st->width=st->max_width;
440 /* check for min height and width */
441 if(st->height < st->minheight)
443 st->height=st->minheight;
445 if(st->width < st->minwidth)
447 st->width=st->minwidth;
450 /* if tiles need to be square, fix it... */
452 st->height=st->width;
454 /* check for sane aspect ratios */
455 if((st->width/st->height) > MAXRATIO)
456 st->height=st->width;
457 if((st->height/st->width) > MAXRATIO)
458 st->width=st->height;
460 /* to avoid linewidths of zero */
461 if(st->linewidth == 0 || st->linewidth < st->minlinewidth)
462 st->linewidth = st->minlinewidth;
464 /* try to keep from getting line widths that would be too big */
465 if(st->linewidth > 0 && st->linewidth >= (st->height/5))
466 st->linewidth = st->height/5;
468 XSetLineAttributes(st->dpy, st->agc, st->linewidth, LineSolid, CapRound, JoinRound);
470 if(st->erase || (st->count >= st->eraseCount))
472 /* XClearWindow(dpy,window); */
473 XFillRectangle(st->dpy, st->frame, st->bgc, 0, 0, st->xgwa.width+st->overlap, st->xgwa.height+st->overlap);
480 /* do the fun stuff...*/
481 if(st->curves && st->angles)
488 else if(st->curves && !st->angles)
490 else if(!st->curves && st->angles)
498 st->scrolling = ((st->overlap / 4) / st->anim_step_size) * 4;
502 XCopyArea(st->dpy,st->frame,st->window,st->agc,0,0,st->xgwa.width,st->xgwa.height,0,0);
508 truchet_reshape (Display *dpy, Window window, void *closure,
509 unsigned int w, unsigned int h)
514 truchet_event (Display *dpy, Window window, void *closure, XEvent *event)
520 truchet_free (Display *dpy, Window window, void *closure)
525 XSCREENSAVER_MODULE ("Truchet", truchet)