From http://www.jwz.org/xscreensaver/xscreensaver-5.35.tar.gz
[xscreensaver] / hacks / barcode.c
1 /* barcode, draw some barcodes
2  * by Dan Bornstein, danfuzz@milk.com
3  * Copyright (c) 2003 Dan Bornstein. All rights reserved.
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and its
6  * documentation for any purpose is hereby granted without fee, provided that
7  * the above copyright notice appear in all copies and that both that
8  * copyright notice and this permission notice appear in supporting
9  * documentation.  No representations are made about the suitability of this
10  * software for any purpose.  It is provided "as is" without express or 
11  * implied warranty.
12  *
13  * See the included man page for more details.
14  */
15
16 #include <math.h>
17 #include <time.h>
18 #include "screenhack.h"
19
20 /* non-user-modifiable immutable definitions */
21
22 #define FLOAT double
23
24 /* random float in the range (0..1) */
25 #define RAND_FLOAT_01 \
26         (((FLOAT) ((random() >> 8) & 0xffff)) / ((FLOAT) 0x10000))
27
28 #define BARCODE_WIDTH (164)
29 #define BARCODE_HEIGHT (69)
30 #define MAX_MAG (7)
31
32
33 /* simple bitmap structure */
34
35 typedef struct
36 {
37     int width;
38     int height;
39     int widthBytes;
40     char *buf;
41 }
42 Bitmap;
43
44
45
46 /* the model */
47
48 typedef struct
49 {
50     int x;          /* x coordinate of the left of the barcode */
51     int y;          /* y coordinate of the left of the barcode */
52     int mag;        /* magnfication factor */
53     Bitmap *bitmap; /* the bitmap */
54     char code[128]; /* the barcode string */
55     unsigned long pixel;  /* the color */
56 }
57 Barcode;
58
59 struct state {
60   Display *dpy;
61   Window window;
62
63   /* parameters that are user configurable */
64
65   /* delay (usec) between iterations */
66   int delay;
67
68   /* width and height of the window */
69   int windowWidth;
70   int windowHeight;
71
72   Visual *visual;          /* the visual to use */
73   Colormap cmap;           /* the colormap of the window */
74
75   GC theGC;                /* GC for drawing */
76   unsigned long fg_pixel, grid_pixel;
77   Bool button_down_p;
78   int grid_alloced_p;
79   char *strings[200];
80
81   Barcode *barcodes; /* array of barcodes */
82   int barcode_count; /* how many barcodes are currently active */
83   int barcode_max;   /* the maximum number of active barcodes */
84
85   XImage *theImage;  /* ginormo image for drawing */
86   Bitmap *theBitmap; /* ginormo bitmap for drawing */
87
88   enum { BC_SCROLL, BC_GRID, BC_CLOCK12, BC_CLOCK24 } mode;
89
90   int grid_w;
91   int grid_h;
92 };
93
94 /* a bunch of words */
95 static const char *words[] = 
96 {
97   "abdomen",
98   "abeyance",
99   "abhorrence",
100   "abrasion",
101   "abstraction",
102   "acid",
103   "addiction",
104   "alertness",
105   "Algeria",
106   "anxiety",
107   "aorta",
108   "argyle socks",
109   "attrition",
110   "axis of evil",
111   "bamboo",
112   "bangle",
113   "bankruptcy",
114   "baptism",
115   "beer",
116   "bellicosity",
117   "bells",
118   "belly",
119   "bliss",
120   "bogosity",
121   "boobies",
122   "boobs",
123   "booty",
124   "bread",
125   "bubba",
126   "burrito",
127   "California",
128   "capybara",
129   "cardinality",
130   "caribou",
131   "carnage",
132   "children",
133   "chocolate",
134   "CLONE",
135   "cock",
136   "constriction",
137   "contrition",
138   "cop",
139   "corpse",
140   "cowboy",
141   "crabapple",
142   "craziness",
143   "cthulhu",
144   "Death",
145   "decepticon",
146   "deception",
147   "Decker",
148   "decoder",
149   "decoy",
150   "defenestration",
151   "democracy",
152   "dependency",
153   "despair",
154   "desperation",
155   "disease",
156   "disease",
157   "doberman",
158   "DOOM",
159   "dreams",
160   "dreams",
161   "drugs",
162   "easy",
163   "ebony",
164   "election",
165   "eloquence",
166   "emergency",
167   "eureka",
168   "excommunication",
169   "fat",
170   "fatherland",
171   "Faust",
172   "fear",
173   "fever",
174   "filth",
175   "flatulence",
176   "fluff",
177   "fnord",
178   "freedom",
179   "fruit",
180   "fruit",
181   "futility",
182   "gerbils",
183   "GOD",
184   "goggles",
185   "goobers",
186   "gorilla",
187   "halibut",
188   "handmaid",
189   "happiness",
190   "hate",
191   "helplessness",
192   "hemorrhoid",
193   "hermaphrodite",
194   "heroin",
195   "heroine",
196   "hope",
197   "hysteria",
198   "icepick",
199   "identity",
200   "ignorance",
201   "importance",
202   "individuality",
203   "inkling",
204   "insurrection",
205   "intoxicant",
206   "ire",
207   "irritant",
208   "jade",
209   "jaundice",
210   "Joyce",
211   "kidney stone",
212   "kitchenette",
213   "kiwi",
214   "lathe",
215   "lattice",
216   "lawyer",
217   "lemming",
218   "liquidation",
219   "lobbyist",
220   "love",
221   "lozenge",
222   "magazine",
223   "magnesium",
224   "malfunction",
225   "marmot",
226   "marshmallow",
227   "merit",
228   "merkin",
229   "mescaline",
230   "milk",
231   "mischief",
232   "mistrust",
233   "money",
234   "monkey",
235   "monkeybutter",
236   "nationalism",
237   "nature",
238   "neuron",
239   "noise",
240   "nomenclature",
241   "nutria",
242   "OBEY",
243   "ocelot",
244   "offspring",
245   "overseer",
246   "pain",
247   "pajamas",
248   "passenger",
249   "passion",
250   "Passover",
251   "peace",
252   "penance",
253   "persimmon",
254   "petticoat",
255   "pharmacist",
256   "PhD",
257   "pitchfork",
258   "plague",
259   "Poindexter",
260   "politician",
261   "pony",
262   "presidency",
263   "prison",
264   "prophecy",
265   "Prozac",
266   "punishment",
267   "punk rock",
268   "punk",
269   "pussy",
270   "quagmire",
271   "quarantine",
272   "quartz",
273   "rabies",
274   "radish",
275   "rage",
276   "readout",
277   "reality",
278   "rectum",
279   "reject",
280   "rejection",
281   "respect",
282   "revolution",
283   "roadrunner",
284   "rule",
285   "savor",
286   "scab",
287   "scalar",
288   "Scandinavia",
289   "schadenfreude",
290   "security",
291   "sediment",
292   "self worth",
293   "sickness",
294   "silicone",
295   "slack",
296   "slander",
297   "slavery",
298   "sledgehammer",
299   "smegma",
300   "smelly socks",
301   "sorrow",
302   "space program",
303   "stamen",
304   "standardization",
305   "stench",
306   "subculture",
307   "subversion",
308   "suffering",
309   "surrender",
310   "surveillance",
311   "synthesis",
312   "television",
313   "tenant",
314   "tendril",
315   "terror",
316   "terrorism",
317   "terrorist",
318   "the impossible",
319   "the unknown",
320   "toast",
321   "topography",
322   "truism",
323   "turgid",
324   "underbrush",
325   "underling",
326   "unguent",
327   "unusual",
328   "uplink",
329   "urge",
330   "valor",
331   "variance",
332   "vaudeville",
333   "vector",
334   "vegetarian",
335   "venom",
336   "verifiability",
337   "viagra",
338   "vibrator",
339   "victim",
340   "vignette",
341   "villainy",
342   "W.A.S.T.E.",
343   "wagon",
344   "waiver",
345   "warehouse",
346   "waste",
347   "waveform",
348   "whiffle ball",
349   "whorl",
350   "windmill",
351   "words",
352   "worm",
353   "worship",
354   "worship",
355   "Xanax",
356   "Xerxes",
357   "Xhosa",
358   "xylophone",
359   "yellow",
360   "yesterday",
361   "your nose",
362   "Zanzibar",
363   "zeal",
364   "zebra",
365   "zest",
366   "zinc"
367 };
368
369 #define WORD_COUNT (sizeof(words) / sizeof(char *))
370
371
372
373 /* ----------------------------------------------------------------------------
374  * bitmap manipulation
375  */
376
377 /* construct a new bitmap */
378 static Bitmap *makeBitmap (int width, int height)
379 {
380     Bitmap *result = malloc (sizeof (Bitmap));
381     result->width = width;
382     result->height = height;
383     result->widthBytes = (width + 7) / 8;
384     result->buf = calloc (1, height * result->widthBytes);
385     return result;
386 }
387
388 /* clear a bitmap */
389 static void bitmapClear (Bitmap *b)
390 {
391     memset (b->buf, 0, b->widthBytes * b->height);
392 }
393
394 #if 0
395 /* free a bitmap */
396 static void bitmapFree (Bitmap *b)
397 {
398     free (b->buf);
399     free (b);
400 }
401 #endif
402
403
404 /* get the byte value at the given byte-offset coordinates in the given
405  * bitmap */
406 static int bitmapGetByte (Bitmap *b, int xByte, int y)
407 {
408     if ((xByte < 0) || 
409         (xByte >= b->widthBytes) || 
410         (y < 0) || 
411         (y >= b->height))
412     {
413         /* out-of-range get returns 0 */
414         return 0;
415     }
416
417     return b->buf[b->widthBytes * y + xByte];
418 }
419
420 /* get the bit value at the given coordinates in the given bitmap */
421 static int bitmapGet (Bitmap *b, int x, int y)
422 {
423     int xbyte = x >> 3;
424     int xbit = x & 0x7;
425     int byteValue = bitmapGetByte (b, xbyte, y);
426
427     return (byteValue & (1 << xbit)) >> xbit;
428 }
429
430 /* set the bit value at the given coordinates in the given bitmap */
431 static void bitmapSet (Bitmap *b, int x, int y, int value)
432 {
433     int xbyte = x >> 3;
434     int xbit = x & 0x7;
435
436     if ((x < 0) || 
437         (x >= b->width) || 
438         (y < 0) || 
439         (y >= b->height))
440     {
441         /* ignore out-of-range set */
442         return;
443     }
444
445     if (value)
446     {
447         b->buf[b->widthBytes * y + xbyte] |= 1 << xbit;
448     }
449     else
450     {
451         b->buf[b->widthBytes * y + xbyte] &= ~(1 << xbit);
452     }
453 }
454
455 /* copy the given rectangle to the given destination from the given source. */
456 static void bitmapCopyRect (Bitmap *dest, int dx, int dy,
457                             Bitmap *src, int sx, int sy, int width, int height)
458 {
459     int x, y;
460
461     for (y = 0; y < height; y++)
462     {
463         for (x = 0; x < width; x++)
464         {
465             bitmapSet (dest, x + dx, y + dy, bitmapGet (src, x + sx, y + sy));
466         }
467     }
468 }
469
470 /* draw a vertical line in the given bitmap */
471 static void bitmapVlin (Bitmap *b, int x, int y1, int y2)
472 {
473     while (y1 <= y2)
474     {
475         bitmapSet (b, x, y1, 1);
476         y1++;
477     }
478 }
479
480 /* scale a bitmap into another bitmap */
481 static void bitmapScale (Bitmap *dest, Bitmap *src, int mag)
482 {
483     int x, y, x2, y2;
484
485     for (y = 0; y < BARCODE_HEIGHT; y++)
486     {
487         for (x = 0; x < BARCODE_WIDTH; x++)
488         {
489             int v = bitmapGet (src, x, y);
490             for (x2 = 0; x2 < mag; x2++) 
491             {
492                 for (y2 = 0; y2 < mag; y2++) 
493                 {
494                     bitmapSet (dest, x * mag + x2, y * mag + y2, v);
495                 }
496             }
497         }
498     }
499 }
500
501
502 /* ----------------------------------------------------------------------------
503  * character generation
504  */
505
506 static unsigned char font5x8Buf[] = 
507 {
508    0x1e, 0x01, 0x06, 0x01, 0x1e, 0x00, 0x1e, 0x01, 0x06, 0x01, 0x1e, 0x00,
509    0x1e, 0x01, 0x1e, 0x01, 0x1e, 0x00, 0x01, 0x00, 0x1f, 0x08, 0x04, 0x08,
510    0x1f, 0x00, 0x11, 0x1f, 0x11, 0x00, 0x1f, 0x01, 0x01, 0x00, 0x1f, 0x04,
511    0x0a, 0x11, 0x00, 0x01, 0x00, 0x0e, 0x11, 0x11, 0x00, 0x0e, 0x11, 0x11,
512    0x0e, 0x00, 0x1f, 0x08, 0x04, 0x08, 0x1f, 0x00, 0x44, 0x41, 0x4e, 0x20,
513    0x42, 0x4f, 0x52, 0x4e, 0x53, 0x54, 0x45, 0x49, 0x4e, 0x21, 0x21, 0x00,
514    0x66, 0x6e, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
515    0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
516    0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
517    0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
518    0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
519    0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
520    0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
521    0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
522    0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
523    0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
524    0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
525    0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
526    0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
527    0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
528    0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
529    0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530    0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x05, 0x05, 0x00,
531    0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x00,
532    0x02, 0x0f, 0x01, 0x0f, 0x08, 0x0f, 0x04, 0x00, 0x0b, 0x0b, 0x08, 0x06,
533    0x01, 0x0d, 0x0d, 0x00, 0x03, 0x05, 0x02, 0x05, 0x0d, 0x05, 0x0b, 0x00,
534    0x04, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x02,
535    0x02, 0x02, 0x04, 0x00, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x00,
536    0x00, 0x09, 0x06, 0x0f, 0x06, 0x09, 0x00, 0x00, 0x00, 0x02, 0x02, 0x07,
537    0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x06, 0x00,
538    0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539    0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x04, 0x06, 0x02, 0x01, 0x01, 0x00,
540    0x0f, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x06, 0x04, 0x04, 0x04,
541    0x04, 0x04, 0x0f, 0x00, 0x0f, 0x09, 0x08, 0x0f, 0x01, 0x09, 0x0f, 0x00,
542    0x0f, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x0f, 0x00, 0x09, 0x09, 0x09, 0x0f,
543    0x08, 0x08, 0x08, 0x00, 0x0f, 0x09, 0x01, 0x0f, 0x08, 0x09, 0x0f, 0x00,
544    0x03, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0c,
545    0x04, 0x04, 0x04, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x0f, 0x00,
546    0x0f, 0x09, 0x09, 0x0f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00,
547    0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x04, 0x06, 0x00,
548    0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x0f, 0x00,
549    0x0f, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x04, 0x02, 0x01, 0x00,
550    0x0f, 0x09, 0x08, 0x0e, 0x02, 0x00, 0x02, 0x00, 0x0f, 0x09, 0x0d, 0x0d,
551    0x0d, 0x01, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x09, 0x00,
552    0x07, 0x09, 0x09, 0x07, 0x09, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x01, 0x01,
553    0x01, 0x01, 0x0f, 0x00, 0x07, 0x09, 0x09, 0x09, 0x09, 0x09, 0x07, 0x00,
554    0x0f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x0f, 0x00, 0x0f, 0x01, 0x01, 0x0f,
555    0x01, 0x01, 0x01, 0x00, 0x0f, 0x01, 0x01, 0x0d, 0x09, 0x09, 0x0f, 0x00,
556    0x09, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x09, 0x00, 0x07, 0x02, 0x02, 0x02,
557    0x02, 0x02, 0x07, 0x00, 0x0e, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x00,
558    0x09, 0x09, 0x09, 0x07, 0x09, 0x09, 0x09, 0x00, 0x01, 0x01, 0x01, 0x01,
559    0x01, 0x01, 0x0f, 0x00, 0x09, 0x0f, 0x0f, 0x0f, 0x09, 0x09, 0x09, 0x00,
560    0x09, 0x0b, 0x0d, 0x09, 0x09, 0x09, 0x09, 0x00, 0x0f, 0x09, 0x09, 0x09,
561    0x09, 0x09, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x01, 0x01, 0x01, 0x00,
562    0x0f, 0x09, 0x09, 0x09, 0x0b, 0x05, 0x0b, 0x00, 0x07, 0x09, 0x09, 0x07,
563    0x09, 0x09, 0x09, 0x00, 0x0f, 0x01, 0x01, 0x0f, 0x08, 0x08, 0x0f, 0x00,
564    0x0f, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x09, 0x09, 0x09, 0x09,
565    0x09, 0x09, 0x0f, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x05, 0x02, 0x00,
566    0x09, 0x09, 0x09, 0x09, 0x0f, 0x0f, 0x09, 0x00, 0x09, 0x09, 0x05, 0x06,
567    0x0a, 0x09, 0x09, 0x00, 0x09, 0x09, 0x09, 0x0f, 0x08, 0x08, 0x0f, 0x00,
568    0x0f, 0x08, 0x08, 0x06, 0x01, 0x01, 0x0f, 0x00, 0x0e, 0x02, 0x02, 0x02,
569    0x02, 0x02, 0x0e, 0x00, 0x01, 0x01, 0x02, 0x06, 0x04, 0x08, 0x08, 0x00,
570    0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x00, 0x02, 0x05, 0x05, 0x00,
571    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
572    0x02, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08,
573    0x0f, 0x09, 0x0f, 0x00, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x09, 0x0f, 0x00,
574    0x00, 0x00, 0x0f, 0x01, 0x01, 0x01, 0x0f, 0x00, 0x08, 0x08, 0x0f, 0x09,
575    0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x09, 0x0f, 0x01, 0x0f, 0x00,
576    0x0e, 0x02, 0x0f, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x09,
577    0x09, 0x0f, 0x08, 0x0c, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x09, 0x09, 0x00,
578    0x02, 0x00, 0x03, 0x02, 0x02, 0x02, 0x07, 0x00, 0x04, 0x00, 0x04, 0x04,
579    0x04, 0x04, 0x05, 0x07, 0x01, 0x01, 0x09, 0x05, 0x03, 0x05, 0x09, 0x00,
580    0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x00, 0x00, 0x09, 0x0f,
581    0x0f, 0x09, 0x09, 0x00, 0x00, 0x00, 0x0f, 0x09, 0x09, 0x09, 0x09, 0x00,
582    0x00, 0x00, 0x0f, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x09,
583    0x09, 0x0f, 0x01, 0x01, 0x00, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x08, 0x08,
584    0x00, 0x00, 0x0f, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x01,
585    0x0f, 0x08, 0x0f, 0x00, 0x00, 0x02, 0x0f, 0x02, 0x02, 0x02, 0x0e, 0x00,
586    0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x09, 0x09,
587    0x09, 0x05, 0x02, 0x00, 0x00, 0x00, 0x09, 0x09, 0x0f, 0x0f, 0x09, 0x00,
588    0x00, 0x00, 0x09, 0x09, 0x06, 0x09, 0x09, 0x00, 0x00, 0x00, 0x09, 0x09,
589    0x09, 0x0f, 0x08, 0x0c, 0x00, 0x00, 0x0f, 0x08, 0x06, 0x01, 0x0f, 0x00,
590    0x08, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08, 0x00, 0x02, 0x02, 0x02, 0x02,
591    0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x04, 0x02, 0x02, 0x01, 0x00,
592    0x00, 0x0a, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
593    0x0f, 0x0f, 0x0f, 0x00
594 };
595
596 static Bitmap font5x8 = { 8, 1024, 1, (char *) font5x8Buf };
597
598 /* draw the given 5x8 character at the given coordinates */
599 static void bitmapDrawChar5x8 (Bitmap *b, int x, int y, char c)
600 {
601     bitmapCopyRect (b, x, y, &font5x8, 0, c * 8, 5, 8);
602 }
603
604 /* draw a string of 5x8 characters at the given coordinates */
605 static void bitmapDrawString5x8 (Bitmap *b, int x, int y, char *str)
606 {
607     int origx = x;
608
609     while (*str != '\0')
610     {
611         char c = *str;
612         if (c == '\n')
613         {
614             x = origx;
615             y += 8;
616         }
617         else
618         {
619             if (c < ' ')
620             {
621                 c = ' ';
622             }
623
624             bitmapDrawChar5x8 (b, x, y, c);
625             x += 5;
626         }
627         str++;
628     }
629 }
630
631
632
633 /* ----------------------------------------------------------------------------
634  * upc/ean symbologies
635  */
636
637 /* A quick lesson in UPC and EAN barcodes: 
638  *
639  * Each digit consists of 2 bars and 2 spaces, taking a total width of 7
640  * times the width of the thinnest possible bar or space. There are three
641  * different possible representations for each digit, used depending on
642  * what side of a two-sided barcode the digit is used on, and to encode
643  * checksum or other information in some cases. The three forms are
644  * related. Taking as the "base" form the pattern as seen on the right-hand
645  * side of a UPC-A barcode, the other forms are the inverse of the base
646  * (that is, bar becomes space and vice versa) and the mirror image of the
647  * base. Still confused? Here's a complete table, where 0 means space and 1
648  * means bar:
649  *
650  *      Left-A   Left-B   Right
651  *      -------  -------  -------
652  *   0  0001101  0100111  1110010
653  *   1  0011001  0110011  1100110
654  *   2  0010011  0011011  1101100
655  *   3  0111101  0100001  1000010
656  *   4  0100011  0011101  1011100
657  *   5  0110001  0111001  1001110
658  *   6  0101111  0000101  1010000
659  *   7  0111011  0010001  1000100
660  *   8  0110111  0001001  1001000
661  *   9  0001011  0010111  1110100
662  *
663  * A UPC-A barcode consists of 6 patterns from Left-A on the left-hand side,
664  * 6 patterns from Right on the right-hand side, a guard pattern of 01010
665  * in the middle, and a guard pattern of 101 on each end. The 12th digit
666  * checksum is calculated as follows: Take the 1st, 3rd, ... 11th digits,
667  * sum them and multiplying by 3, and add that to the sum of the other digits.
668  * Subtract the final digit from 10, and that is the checksum digit. (If
669  * the last digit of the sum is 0, then the check digit is 0.)
670  *
671  * An EAN-13 barcode is just like a UPC-A barcode, except that the characters
672  * on the left-hand side have a pattern of Left-A and Left-B that encodes
673  * an extra first digit. Note that an EAN-13 barcode with the first digit
674  * of 0 is exactly the same as the UPC-A barcode of the rightmost 12 digits.
675  * The patterns to encode the first digit are as follows:
676  *
677  *      Left-Hand 
678  *      Digit Position
679  *      1 2 3 4 5 6
680  *      - - - - - -
681  *   0  a a a a a a
682  *   1  a a b a b b
683  *   2  a a b b a b
684  *   3  a a b b b a
685  *   4  a b a a b b
686  *   5  a b b a a b
687  *   6  a b b b a a
688  *   7  a b a b a b
689  *   8  a b a b b a
690  *   9  a b b a b a
691  *
692  * The checksum for EAN-13 is just like UPC-A, except the 2nd, 4th, ... 12th
693  * digits are multiplied by 3 instead of the other way around.
694  *
695  * An EAN-8 barcode is just like a UPC-A barcode, except there are only 4
696  * digits in each half. Unlike EAN-13, there's no nonsense about different
697  * left-hand side patterns, either.
698  *
699  * A UPC-E barcode contains 6 explicit characters between a guard of 101
700  * on the left and 010101 on the right. The explicit characters are the
701  * middle six characters of the code. The first and last characters are
702  * encoded in the parity pattern of the six characters. There are two
703  * sets of parity patterns, one to use if the first digit of the number
704  * is 0, and another if it is 1. (UPC-E barcodes may only start with a 0
705  * or 1.) The patterns are as follows:
706  *
707  *      First digit 0     First digit 1
708  *      Explicit Digit    Explicit Digit
709  *      Position          Position
710  *      1 2 3 4 5 6       1 2 3 4 5 6
711  *      - - - - - -       - - - - - -
712  *   0  b b b a a a       a a a b b b
713  *   1  b b a b a a       a a b a b b
714  *   2  b b a a b a       a a b b a b
715  *   3  b b a a a b       a a b b b a
716  *   4  b a b b a a       a b a a b b
717  *   5  b a a b b a       a b b a a b
718  *   6  b a a a b b       a b b b a a
719  *   7  b a b a b a       a b a b a b
720  *   8  b a b a a b       a b a b b a
721  *   9  b a a b a b       a b b a b a
722  *
723  * (Note that the two sets are the complements of each other. Also note
724  * that the first digit 1 patterns are mostly the same as the EAN-13
725  * first digit patterns.) The UPC-E check digit (the final digit encoded in
726  * the parity pattern) is the same as the UPC-A check digit for the
727  * expanded form of the UPC-E number. The expanstion is as follows, based
728  * on the last explicit digit (the second to last digit) in the encoded
729  * number:
730  *
731  *               Corresponding
732  *   UPC-E form  UPC-A form
733  *   ----------  -------------
734  *   XABCDE0Y    XAB00000CDEY
735  *   XABCDE1Y    XAB10000CDEY
736  *   XABCDE2Y    XAB20000CDEY
737  *   XABCDE3Y    XABC00000DEY
738  *   XABCDE4Y    XABCD00000EY
739  *   XABCDE5Y    XABCDE00005Y
740  *   XABCDE6Y    XABCDE00006Y
741  *   XABCDE7Y    XABCDE00007Y
742  *   XABCDE8Y    XABCDE00008Y
743  *   XABCDE9Y    XABCDE00009Y 
744  *
745  * All UPC/EAN barcodes may have an additional 2- or 5-digit supplemental
746  * code just to the right of the main barcode. The supplement starts about
747  * one digit-length (that is about 7 times the width of the thinnest bar)
748  * to the right of the main code, beginning with the guard pattern 1011.
749  * After that comes each digit, with a guard pattern of 01 between each,
750  * but not at the end. The digits are encoded using the left A and B
751  * characters to encode a parity pattern.
752  *
753  * For 2-digit supplements, the parity pattern is determined by the
754  * lower two bits of the numeric value of the code (e.g., 42 would use
755  * pattern 2):
756  *
757  *   Lower 2 bits  Parity Pattern
758  *   ------------  --------------
759  *   0 (bin 00)    a a
760  *   1 (bin 01)    a b
761  *   2 (bin 10)    b a
762  *   3 (bin 11)    b b
763  *
764  * For 5-digit supplements, the parity pattern is calculated in a similar
765  * manner to check digit calculation: The first, third, and fifth digits
766  * are summed and multiplied by 3; the second and fourth digits are summed
767  * and multiplied by nine; the parity digit is the sum of those two numbers,
768  * modulo 10. The parity pattern is then the last five patterns from the
769  * UPC-E final digit 0 table for the corresponding digit.
770  */
771
772 /* enum to indicate which pattern set to use */
773 typedef enum
774 {
775     UPC_LEFT_A, UPC_LEFT_B, UPC_RIGHT
776 }
777 UpcSet;
778
779 /* the Left A patterns */
780 static unsigned int upcLeftA[] = { 
781     0x0d, 0x19, 0x13, 0x3d, 0x23, 0x31, 0x2f, 0x3b, 0x37, 0x0b 
782 };
783
784 /* the Left B patterns */
785 static unsigned int upcLeftB[] = { 
786     0x27, 0x33, 0x1b, 0x21, 0x1d, 0x39, 0x05, 0x11, 0x09, 0x17
787 };
788
789 /* the Right patterns */
790 static unsigned int upcRight[] = { 
791     0x72, 0x66, 0x6c, 0x42, 0x5c, 0x4e, 0x50, 0x44, 0x48, 0x74
792 };
793
794 /* the EAN-13 first-digit patterns */
795 static unsigned int ean13FirstDigit[] = {
796     0x00, 0x0b, 0x0d, 0x0e, 0x13, 0x19, 0x1c, 0x15, 0x16, 0x1a
797 };
798
799 /* the UPC-E last-digit patterns for first digit 0 (complement for
800  * digit 1); also used for 5-digit supplemental check patterns */
801 static unsigned int upcELastDigit[] = {
802     0x38, 0x34, 0x32, 0x31, 0x2c, 0x26, 0x23, 0x2a, 0x29, 0x25
803 };
804
805 /* turn a character into an int representing its digit value; return
806  * 0 for things not in the range '0'-'9' */
807 static int charToDigit (char c)
808 {
809     if ((c >= '0') && (c <= '9'))
810     {
811         return c - '0';
812     }
813     else
814     {
815         return 0;
816     }
817 }
818
819 /* draw the given digit character at the given coordinates; a '0' is
820  * used in place of any non-digit character */
821 static void drawDigitChar (struct state *st, Bitmap *b, int x, int y, char c)
822 {
823   if (st->mode != BC_CLOCK24 &&
824       st->mode != BC_CLOCK12)
825     if ((c < '0') || (c > '9'))
826       c = '0';
827
828   bitmapDrawChar5x8 (b, x, y, c);
829 }
830
831 /* draw a upc/ean digit at the given coordinates */
832 static void drawUpcEanDigit (Bitmap *upcBitmap, int x, int y1, int y2, char n, 
833                              UpcSet set)
834 {
835     unsigned int bits;
836     int i;
837     
838     n = charToDigit (n);
839     switch (set)
840     {
841         case UPC_LEFT_A: 
842             bits = upcLeftA[(int) n];
843             break;
844         case UPC_LEFT_B: 
845             bits = upcLeftB[(int) n];
846             break;
847         default /* case UPC_RIGHT */:
848             bits = upcRight[(int) n];
849             break;
850     }
851
852     for (i = 6; i >=0; i--)
853     {
854         if (bits & (1 << i))
855         {
856             bitmapVlin (upcBitmap, x, y1, y2);
857         }
858         x++;
859     }
860 }
861
862 /* report the width of the given supplemental code or 0 if it is a bad
863  * supplement form */
864 static int upcEanSupplementWidth (char *digits)
865 {
866     switch (strlen (digits))
867     {
868         case 2: return 28; /* 8 + 4 + 2*7 + 1*2 */
869         case 5: return 55; /* 8 + 4 + 5*7 + 4*2 */
870         default: return 0;
871     }
872 }
873
874 /* draw the given supplemental barcode, including the textual digits */
875 static void drawUpcEanSupplementalBars (struct state *st, 
876                                         Bitmap *upcBitmap, char *digits, 
877                                         int x, int y, int y2, int textAbove)
878 {
879     int len = strlen (digits);
880     int i;
881     int parity;
882     int textY;
883     int textX;
884
885     if (textAbove)
886     {
887         textY = y;
888         y += 8;
889     }
890     else
891     {
892         y2 -= 8;
893         textY = y2 + 2;
894     }
895
896     x += 8; /* skip the space between the main and supplemental */
897
898     switch (len)
899     {
900         case 2: 
901         {
902             textX = x + 5;
903             parity = (charToDigit (digits[0]) * 10 + 
904                       charToDigit (digits[1])) & 0x3;
905             break;
906         }
907         case 5:
908         {
909             textX = x + 10;
910             parity = 
911                 ((charToDigit (digits[0]) + charToDigit (digits[2]) + 
912                   charToDigit (digits[4])) * 3
913                  + (charToDigit (digits[1]) + charToDigit (digits[3])) * 9)
914                 % 10;
915             parity = upcELastDigit[parity];
916             break;
917         }
918         default:
919         {
920             fprintf (stderr, "%s: bad supplement (%d digits)\n",
921                      progname, len);
922             exit(1);
923             break;
924         }
925     }
926
927     /* header */
928     bitmapVlin (upcBitmap, x, y, y2);
929     bitmapVlin (upcBitmap, x + 2, y, y2);
930     bitmapVlin (upcBitmap, x + 3, y, y2);
931
932     for (i = 0; i < len; i++)
933     {
934         UpcSet lset = 
935             (parity & (1 << (len - 1 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
936         int baseX = x + 2 + i * 9;
937
938         /* separator / end of header */
939         if (i == 0)
940         {
941             bitmapVlin (upcBitmap, baseX, y, y2);
942         }
943         bitmapVlin (upcBitmap, baseX + 1, y, y2);
944
945         drawUpcEanDigit (upcBitmap,
946                          baseX + 2, 
947                          y,
948                          y2,
949                          digits[i], 
950                          lset);
951
952         drawDigitChar (st, upcBitmap, textX + i*6, textY, digits[i]);
953     }
954 }
955
956 /* draw the actual barcode part of a UPC-A barcode */
957 static void drawUpcABars (Bitmap *upcBitmap, char *digits, int x, int y, 
958                           int barY2, int guardY2)
959 {
960     int i;
961
962     /* header */
963     bitmapVlin (upcBitmap, x, y, guardY2);
964     bitmapVlin (upcBitmap, x + 2, y, guardY2);
965
966     /* center marker */
967     bitmapVlin (upcBitmap, x + 46, y, guardY2);
968     bitmapVlin (upcBitmap, x + 48, y, guardY2);
969
970     /* trailer */
971     bitmapVlin (upcBitmap, x + 92, y, guardY2);
972     bitmapVlin (upcBitmap, x + 94, y, guardY2);
973
974     for (i = 0; i < 6; i++)
975     {
976         drawUpcEanDigit (upcBitmap,
977                          x + 3 + i*7, 
978                          y,
979                          (i == 0) ? guardY2 : barY2,
980                          digits[i], 
981                          UPC_LEFT_A);
982         drawUpcEanDigit (upcBitmap,
983                          x + 50 + i*7, 
984                          y, 
985                          (i == 5) ? guardY2 : barY2,
986                          digits[i+6], 
987                          UPC_RIGHT);
988     }
989 }
990
991 /* make and return a full-height UPC-A barcode */
992 static int makeUpcAFull (struct state *st, Bitmap *dest, char *digits, int y)
993 {
994     int baseWidth = 108;
995     int baseHeight = 60;
996
997     int height = baseHeight + y;
998     int i;
999
1000     bitmapClear (dest);
1001     drawUpcABars (dest, digits, 6, y, height - 10, height - 4);
1002
1003     drawDigitChar (st, dest, 0, height - 14, digits[0]);
1004
1005     for (i = 0; i < 5; i++)
1006     {
1007         drawDigitChar (st, dest, 18 + i*7, height - 7, digits[i+1]);
1008         drawDigitChar (st, dest, 57 + i*7, height - 7, digits[i+6]);
1009     }
1010
1011     drawDigitChar (st, dest, 103, height - 14, digits[11]);
1012
1013     return baseWidth;
1014 }
1015
1016 /* make and return a UPC-A barcode */
1017 static int makeUpcA (struct state *st, Bitmap *dest, char *digits, int y)
1018 {
1019     int i;
1020     unsigned int mul = 3;
1021     unsigned int sum = 0;
1022
1023     for (i = 0; i < 11; i++)
1024     {
1025         sum += charToDigit (digits[i]) * mul;
1026         mul ^= 2;
1027     }
1028
1029     if (digits[11] == '?')
1030     {
1031         digits[11] = ((10 - (sum % 10)) % 10) + '0';
1032     }
1033
1034     return makeUpcAFull (st, dest, digits, y);
1035 }
1036
1037 /* draw the actual barcode part of a UPC-E barcode */
1038 static void drawUpcEBars (struct state *st, 
1039                           Bitmap *upcBitmap, char *digits, int x, int y, 
1040                           int barY2, int guardY2)
1041 {
1042     int i;
1043     int parityPattern = upcELastDigit[charToDigit(digits[7])];
1044
1045     int clockp = (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24);
1046
1047     if (digits[0] == '1')
1048     {
1049         parityPattern = ~parityPattern;
1050     }
1051
1052     /* header */
1053     bitmapVlin (upcBitmap, x,     y, guardY2);
1054     bitmapVlin (upcBitmap, x + 2, y, guardY2);
1055
1056     /* trailer */
1057     bitmapVlin (upcBitmap, x + 46 + (clockp?8:0), y, guardY2);
1058     bitmapVlin (upcBitmap, x + 48 + (clockp?8:0), y, guardY2);
1059     bitmapVlin (upcBitmap, x + 50 + (clockp?8:0), y, guardY2);
1060
1061     /* clock kludge -- this draws an extra set of dividers after
1062        digits 2 and 4.  This makes this *not* be a valid bar code,
1063        but, it looks pretty for the clock dpy.
1064      */
1065     if (clockp)
1066       {
1067         bitmapVlin (upcBitmap, x + 18,     y, guardY2);
1068         bitmapVlin (upcBitmap, x + 18 + 2, y, guardY2);
1069
1070         bitmapVlin (upcBitmap, x + 36,     y, guardY2);
1071         bitmapVlin (upcBitmap, x + 36 + 2, y, guardY2);
1072       }
1073
1074     for (i = 0; i < 6; i++)
1075     {
1076         UpcSet lset = 
1077             (parityPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
1078         int off = (clockp
1079                    ? (i < 2 ? 0 :
1080                       i < 4 ? 4 :      /* extra spacing for clock bars */
1081                               8)
1082                    : 0);
1083         drawUpcEanDigit (upcBitmap,
1084                          x + 3 + i*7 + off,
1085                          y,
1086                          barY2,
1087                          digits[i + 1], 
1088                          lset);
1089     }
1090 }
1091
1092 /* make and return a full-height UPC-E barcode */
1093 static int makeUpcEFull (struct state *st, Bitmap *dest, char *digits, int y)
1094 {
1095     int baseWidth = 64;
1096     int baseHeight = 60;
1097
1098     int height = baseHeight + y;
1099     int i;
1100
1101     bitmapClear (dest);
1102     drawUpcEBars (st, dest, digits, 6, y, height - 10, height - 4);
1103
1104     drawDigitChar (st, dest, 0, height - 14, digits[0]);
1105
1106     for (i = 0; i < 6; i++)
1107     {
1108         drawDigitChar (st, dest, 11 + i*7, height - 7, digits[i+1]);
1109     }
1110
1111     drawDigitChar (st, dest, 59, height - 14, digits[7]);
1112
1113     return baseWidth;
1114 }
1115
1116 /* expand 8 UPC-E digits into a UPC-A number, storing into the given result
1117  * array, or just store '\0' into the first element, if the form factor
1118  * is incorrect; this will also calculate the check digit, if it is
1119  * specified as '?' */
1120 static void expandToUpcADigits (char *compressed, char *expanded)
1121 {
1122     int i;
1123
1124     if ((compressed[0] != '0') && (compressed[0] != '1'))
1125     {
1126         return;
1127     }
1128
1129     expanded[0] = compressed[0];
1130     expanded[6] = '0';
1131     expanded[7] = '0';
1132     expanded[11] = compressed[7];
1133
1134     switch (compressed[6])
1135     {
1136         case '0':
1137         case '1':
1138         case '2':
1139         {
1140             expanded[1] = compressed[1];
1141             expanded[2] = compressed[2];
1142             expanded[3] = compressed[6];
1143             expanded[4] = '0';
1144             expanded[5] = '0';
1145             expanded[8] = compressed[3];
1146             expanded[9] = compressed[4];
1147             expanded[10] = compressed[5];
1148             break;
1149         }
1150         case '3':
1151         {
1152             expanded[1] = compressed[1];
1153             expanded[2] = compressed[2];
1154             expanded[3] = compressed[3];
1155             expanded[4] = '0';
1156             expanded[5] = '0';
1157             expanded[8] = '0';
1158             expanded[9] = compressed[4];
1159             expanded[10] = compressed[5];
1160             break;
1161         }
1162         case '4':
1163         {
1164             expanded[1] = compressed[1];
1165             expanded[2] = compressed[2];
1166             expanded[3] = compressed[3];
1167             expanded[4] = compressed[4];
1168             expanded[5] = '0';
1169             expanded[8] = '0';
1170             expanded[9] = '0';
1171             expanded[10] = compressed[5];
1172             break;
1173         }
1174         default:
1175         {
1176             expanded[1] = compressed[1];
1177             expanded[2] = compressed[2];
1178             expanded[3] = compressed[3];
1179             expanded[4] = compressed[4];
1180             expanded[5] = compressed[5];
1181             expanded[8] = '0';
1182             expanded[9] = '0';
1183             expanded[10] = compressed[6];
1184             break;
1185         }
1186     }
1187
1188     if (expanded[11] == '?')
1189     {
1190         unsigned int mul = 3;
1191         unsigned int sum = 0;
1192
1193         for (i = 0; i < 11; i++)
1194         {
1195             sum += charToDigit (expanded[i]) * mul;
1196             mul ^= 2;
1197         }
1198
1199         expanded[11] = ((10 - (sum % 10)) % 10) + '0';
1200     }
1201 }
1202
1203 /* make and return a UPC-E barcode */
1204 static int makeUpcE (struct state *st, Bitmap *dest, char *digits, int y)
1205 {
1206     char expandedDigits[13];
1207     char compressedDigits[9];
1208
1209     expandedDigits[0] = '\0';
1210     compressedDigits[0] = '0';
1211     strcpy (compressedDigits + 1, digits);
1212
1213     expandToUpcADigits (compressedDigits, expandedDigits);
1214     if (expandedDigits[0] == '\0')
1215     {
1216         return 0;
1217     }
1218     
1219     compressedDigits[7] = expandedDigits[11];
1220
1221     return makeUpcEFull (st, dest, compressedDigits, y);
1222 }
1223
1224 /* draw the actual barcode part of a EAN-13 barcode */
1225 static void drawEan13Bars (Bitmap *upcBitmap, char *digits, int x, int y, 
1226                            int barY2, int guardY2)
1227 {
1228     int i;
1229     int leftPattern = ean13FirstDigit[charToDigit (digits[0])];
1230
1231     /* header */
1232     bitmapVlin (upcBitmap, x, y, guardY2);
1233     bitmapVlin (upcBitmap, x + 2, y, guardY2);
1234
1235     /* center marker */
1236     bitmapVlin (upcBitmap, x + 46, y, guardY2);
1237     bitmapVlin (upcBitmap, x + 48, y, guardY2);
1238
1239     /* trailer */
1240     bitmapVlin (upcBitmap, x + 92, y, guardY2);
1241     bitmapVlin (upcBitmap, x + 94, y, guardY2);
1242
1243     for (i = 0; i < 6; i++)
1244     {
1245         UpcSet lset = (leftPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
1246
1247         drawUpcEanDigit (upcBitmap,
1248                          x + 3 + i*7, 
1249                          y,
1250                          barY2,
1251                          digits[i+1], 
1252                          lset);
1253         drawUpcEanDigit (upcBitmap,
1254                          x + 50 + i*7, 
1255                          y, 
1256                          barY2,
1257                          digits[i+7], 
1258                          UPC_RIGHT);
1259     }
1260 }
1261
1262 /* make and return a full-height EAN-13 barcode */
1263 static int makeEan13Full (struct state *st, Bitmap *dest, char *digits, int y)
1264 {
1265     int baseWidth = 102;
1266     int baseHeight = 60;
1267
1268     int height = baseHeight + y;
1269     int i;
1270
1271     bitmapClear (dest);
1272     drawEan13Bars (dest, digits, 6, y, height - 10, height - 4);
1273
1274     drawDigitChar (st, dest, 0, height - 7, digits[0]);
1275
1276     for (i = 0; i < 6; i++)
1277     {
1278         drawDigitChar (st, dest, 11 + i*7, height - 7, digits[i+1]);
1279         drawDigitChar (st, dest, 57 + i*7, height - 7, digits[i+7]);
1280     }
1281
1282     return baseWidth;
1283 }
1284
1285 /* make and return an EAN-13 barcode */
1286 static int makeEan13 (struct state *st, Bitmap *dest, char *digits, int y)
1287 {
1288     int i;
1289     unsigned int mul = 1;
1290     unsigned int sum = 0;
1291
1292     for (i = 0; i < 12; i++)
1293     {
1294         sum += charToDigit (digits[i]) * mul;
1295         mul ^= 2;
1296     }
1297
1298     if (digits[12] == '?')
1299     {
1300         digits[12] = ((10 - (sum % 10)) % 10) + '0';
1301     }
1302
1303     return makeEan13Full (st, dest, digits, y);
1304 }
1305
1306 /* draw the actual barcode part of an EAN-8 barcode */
1307 static void drawEan8Bars (Bitmap *upcBitmap, char *digits, int x, int y, 
1308                           int barY2, int guardY2)
1309 {
1310     int i;
1311
1312     /* header */
1313     bitmapVlin (upcBitmap, x, y, guardY2);
1314     bitmapVlin (upcBitmap, x + 2, y, guardY2);
1315
1316     /* center marker */
1317     bitmapVlin (upcBitmap, x + 32, y, guardY2);
1318     bitmapVlin (upcBitmap, x + 34, y, guardY2);
1319
1320     /* trailer */
1321     bitmapVlin (upcBitmap, x + 64, y, guardY2);
1322     bitmapVlin (upcBitmap, x + 66, y, guardY2);
1323
1324     for (i = 0; i < 4; i++)
1325     {
1326         drawUpcEanDigit (upcBitmap,
1327                          x + 3 + i*7, 
1328                          y,
1329                          barY2,
1330                          digits[i], 
1331                          UPC_LEFT_A);
1332         drawUpcEanDigit (upcBitmap,
1333                          x + 36 + i*7, 
1334                          y, 
1335                          barY2,
1336                          digits[i+4], 
1337                          UPC_RIGHT);
1338     }
1339 }
1340
1341 /* make and return a full-height EAN-8 barcode */
1342 static int makeEan8Full (struct state *st, Bitmap *dest, char *digits, int y)
1343 {
1344     int baseWidth = 68;
1345     int baseHeight = 60;
1346
1347     int height = baseHeight + y;
1348     int i;
1349
1350     bitmapClear (dest);
1351     drawEan8Bars (dest, digits, 0, y, height - 10, height - 4);
1352
1353     for (i = 0; i < 4; i++)
1354     {
1355         drawDigitChar (st, dest, 5 + i*7, height - 7, digits[i]);
1356         drawDigitChar (st, dest, 37 + i*7, height - 7, digits[i+4]);
1357     }
1358
1359     return baseWidth;
1360 }
1361
1362 /* make and return an EAN-8 barcode */
1363 static int makeEan8 (struct state *st, Bitmap *dest, char *digits, int y)
1364 {
1365     int i;
1366     unsigned int mul = 3;
1367     unsigned int sum = 0;
1368
1369     for (i = 0; i < 7; i++)
1370     {
1371         sum += charToDigit (digits[i]) * mul;
1372         mul ^= 2;
1373     }
1374
1375     if (digits[7] == '?')
1376     {
1377         digits[7] = ((10 - (sum % 10)) % 10) + '0';
1378     }
1379
1380     return makeEan8Full (st, dest, digits, y);
1381 }
1382
1383 /* Dispatch to the right form factor UPC/EAN barcode generator */
1384 static void processUpcEan (struct state *st, char *str, Bitmap *dest)
1385 {
1386     char digits[16];
1387     int digitCount = 0;
1388     char supDigits[8];
1389     int supDigitCount = 0;
1390     char *instr = str;
1391     char *banner = NULL; 
1392     int supplement = 0;
1393     int vstart = 9;
1394     int width = 0;
1395
1396     while ((digitCount < 15) && (supDigitCount < 7))
1397     {
1398         char c = *instr;
1399         if (((c >= '0') && (c <= '9')) || (c == '?'))
1400         {
1401             if (supplement)
1402             {
1403                 supDigits[supDigitCount] = *instr;
1404                 supDigitCount++;
1405             }
1406             else
1407             {
1408                 digits[digitCount] = *instr;
1409                 digitCount++;
1410             }
1411         }
1412         else if (c == ',')
1413         {
1414             supplement = 1;
1415         }
1416         else if (c == ':')
1417         {
1418             banner = instr + 1;
1419             break;
1420         }
1421         else if (c == '\0')
1422         {
1423             break;
1424         }
1425         instr++;
1426     }
1427
1428     digits[digitCount] = '\0';
1429     supDigits[supDigitCount] = '\0';
1430
1431     if (supDigitCount == 0)
1432     {
1433         supplement = 0;
1434     }
1435     else if ((supDigitCount == 2) || (supDigitCount == 5))
1436     {
1437         supplement = upcEanSupplementWidth (supDigits);
1438     }
1439     else
1440     {
1441         fprintf (stderr, "%s: invalid supplement (must be 2 or 5 digits)\n",
1442                  progname);
1443         exit (1);
1444     }
1445
1446     if (banner == NULL) 
1447     {
1448         banner = "barcode";
1449     }
1450
1451     switch (digitCount)
1452     {
1453         case 7: 
1454         {
1455             width = makeUpcE (st, dest, digits, vstart);
1456             break;
1457         }
1458         case 8: 
1459         {
1460             width = makeEan8 (st, dest, digits, vstart);
1461             break;
1462         }
1463         case 12: 
1464         {
1465             width = makeUpcA (st, dest, digits, vstart);
1466             break;
1467         }
1468         case 13:
1469         {
1470             width = makeEan13 (st, dest, digits, vstart);
1471             break;
1472         }
1473         default:
1474         {
1475             fprintf (stderr, "%s: bad barcode (%d digits)\n",
1476                      progname, digitCount);
1477             exit(1);
1478         }
1479     }
1480
1481     if (supplement)
1482     {
1483         drawUpcEanSupplementalBars (st, dest, supDigits,
1484                                     width,
1485                                     vstart + 1, dest->height - 4, 1);
1486     }
1487
1488     if (banner != NULL)
1489     {
1490         bitmapDrawString5x8 (dest, 
1491                              (width + supplement -
1492                               ((int) strlen (banner) * 5)) / 2,
1493                              0,
1494                              banner);
1495     }
1496 }
1497
1498
1499
1500 /* ----------------------------------------------------------------------------
1501  * the screenhack
1502  */
1503
1504 /*
1505  * overall setup stuff
1506  */
1507
1508 /* set up the system */
1509 static void setup (struct state *st)
1510 {
1511     XWindowAttributes xgwa;
1512     XGCValues gcv;
1513
1514     XGetWindowAttributes (st->dpy, st->window, &xgwa);
1515
1516     st->visual = xgwa.visual;
1517     st->cmap = xgwa.colormap;
1518     st->windowWidth = xgwa.width;
1519     st->windowHeight = xgwa.height;
1520
1521     gcv.background = get_pixel_resource (st->dpy, xgwa.colormap,
1522                                          "background", "Background");
1523     gcv.foreground = get_pixel_resource (st->dpy, xgwa.colormap,
1524                                          "foreground", "Foreground");
1525     st->fg_pixel = gcv.foreground;
1526     st->theGC = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv);
1527
1528     st->theBitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG, BARCODE_HEIGHT * MAX_MAG);
1529     st->theImage = XCreateImage(st->dpy, st->visual, 1, XYBitmap, 0, st->theBitmap->buf,
1530                             st->theBitmap->width, st->theBitmap->height, 8,
1531                             st->theBitmap->widthBytes);
1532     st->theImage->bitmap_bit_order = LSBFirst;
1533     st->theImage->byte_order       = LSBFirst;
1534 }
1535
1536
1537
1538 /*
1539  * the simulation
1540  */
1541
1542 /* set up the model */
1543 static void setupModel (struct state *st)
1544 {
1545     int i;
1546
1547     st->barcode_max = 20;
1548     st->barcode_count = 0;
1549     st->barcodes = malloc (sizeof (Barcode) * st->barcode_max);
1550
1551     for (i = 0; i < st->barcode_max; i++)
1552     {
1553         st->barcodes[i].bitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG, 
1554                                         BARCODE_HEIGHT * MAX_MAG);
1555     }
1556 }
1557
1558 /* make a new barcode string */
1559 static void makeBarcodeString (struct state *st, char *str)
1560 {
1561     int dig, i;
1562
1563     switch ((int) (RAND_FLOAT_01 * 4))
1564     {
1565         case 0:  dig = 6;  break;
1566         case 1:  dig = 7;  break;
1567         case 2:  dig = 11; break;
1568         default: dig = 12; break;
1569     }
1570
1571     for (i = 0; i < dig; i++)
1572     {
1573         str[i] = RAND_FLOAT_01 * 10 + '0';
1574     }
1575
1576     str[i] = '?';
1577     i++;
1578
1579     switch ((int) (RAND_FLOAT_01 * 3))
1580     {
1581         case 0:  dig = 0; break;
1582         case 1:  dig = 2; break;
1583         default: dig = 5; break;
1584     }
1585
1586     if (dig != 0)
1587     {
1588         str[i] = ',';
1589         i++;
1590         while (dig > 0) 
1591         {
1592             str[i] = RAND_FLOAT_01 * 10 + '0';
1593             i++;
1594             dig--;
1595         }
1596     }
1597
1598     str[i] = ':';
1599     i++;
1600
1601     strcpy(&str[i], words[(int) (RAND_FLOAT_01 * WORD_COUNT)]);
1602 }
1603
1604 /* update the model for one iteration */
1605 static void scrollModel (struct state *st)
1606 {
1607     int i;
1608
1609     for (i = 0; i < st->barcode_count; i++) 
1610     {
1611         Barcode *b = &st->barcodes[i];
1612         b->x--;
1613         if ((b->x + BARCODE_WIDTH * b->mag) < 0) 
1614         {
1615             /* fell off the edge */
1616             if (i != (st->barcode_count - 1)) {
1617                 Bitmap *oldb = b->bitmap;
1618                 memmove (b, b + 1, (st->barcode_count - i - 1) * sizeof (Barcode));
1619                 st->barcodes[st->barcode_count - 1].bitmap = oldb;
1620
1621                 XFreeColors (st->dpy, st->cmap, &b->pixel, 1, 0);
1622             }
1623
1624             i--;
1625             st->barcode_count--;
1626         }
1627     }
1628
1629     while (st->barcode_count < st->barcode_max)
1630     {
1631         Barcode *barcode = &st->barcodes[st->barcode_count];
1632         barcode->x = (st->barcode_count == 0) ? 
1633             0 : 
1634             (st->barcodes[st->barcode_count - 1].x + 
1635              st->barcodes[st->barcode_count - 1].mag * BARCODE_WIDTH);
1636         barcode->x += RAND_FLOAT_01 * 100;
1637         barcode->mag = RAND_FLOAT_01 * MAX_MAG;
1638         barcode->y =
1639             RAND_FLOAT_01 * (st->windowHeight - BARCODE_HEIGHT * barcode->mag);
1640         if (barcode->y < 0) 
1641         {
1642             barcode->y = 0;
1643         }
1644         makeBarcodeString(st, barcode->code);
1645         processUpcEan (st, barcode->code, st->theBitmap);
1646         bitmapScale (barcode->bitmap, st->theBitmap, barcode->mag);
1647
1648         {
1649           XColor c;
1650           int ii, ok = 0;
1651           for (ii = 0; ii < 100; ii++)
1652             {
1653               hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1654               ok = XAllocColor (st->dpy, st->cmap, &c);
1655               if (ok) break;
1656             }
1657           if (!ok)
1658             {
1659               c.red = c.green = c.blue = 0xFFFF;
1660               if (!XAllocColor (st->dpy, st->cmap, &c))
1661                 abort();
1662             }
1663           barcode->pixel = c.pixel;
1664         }
1665
1666         st->barcode_count++;
1667     }
1668 }
1669
1670 /* update the model for one iteration */
1671 static void updateGrid (struct state *st)
1672 {
1673     int i, x, y;
1674
1675     if (st->grid_w == 0 || st->grid_h == 0 ||
1676         (! (random() % 400)))
1677       {
1678         XClearWindow (st->dpy, st->window);
1679         st->grid_w = 1 + (random() % 3);
1680         st->grid_h = 1 + (random() % 4);
1681       }
1682
1683     if (!st->grid_alloced_p || (! (random() % 100)))
1684       {
1685         XColor c;
1686         hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1687         if (st->grid_alloced_p)
1688           XFreeColors (st->dpy, st->cmap, &st->grid_pixel, 1, 0);
1689         XAllocColor (st->dpy, st->cmap, &c);
1690         st->grid_pixel = c.pixel;
1691         st->grid_alloced_p = 1;
1692       }
1693
1694     st->barcode_count = st->grid_w * st->grid_h;
1695     if (st->barcode_count > st->barcode_max) abort();
1696
1697     for (i = 0; i < st->barcode_max; i++)
1698       {
1699         Barcode *b = &st->barcodes[i];
1700         b->x = b->y = 999999;
1701       }
1702
1703     i = 0;
1704     for (y = 0; y < st->grid_h; y++)
1705       for (x = 0; x < st->grid_w; x++, i++)
1706         {
1707           Barcode *b = &st->barcodes[i];
1708           int digits = 12;
1709
1710           int cell_w = (st->windowWidth  / st->grid_w);
1711           int cell_h = (st->windowHeight / st->grid_h);
1712           int mag_x  = cell_w / BARCODE_WIDTH;
1713           int mag_y  = cell_h / BARCODE_HEIGHT;
1714           int BW = 108 /*BARCODE_WIDTH*/;
1715           int BH = BARCODE_HEIGHT;
1716
1717           b->mag = (mag_x < mag_y ? mag_x : mag_y);
1718
1719           b->x = (x * cell_w) + ((cell_w - b->mag * BW) / 2);
1720           b->y = (y * cell_h) + ((cell_h - b->mag * BH) / 2);
1721           b->pixel = st->grid_pixel;
1722
1723           if (!st->strings[i])
1724             {
1725               int j;
1726               char *s = malloc (digits + 10);
1727               st->strings[i] = s;
1728               for (j = 0; j < digits; j++)
1729                 s[j] = (random() % 10) + '0';
1730               s[j++] = '?';
1731               s[j++] = ':';
1732               s[j] = 0;
1733             }
1734
1735           /* change one digit in this barcode */
1736           st->strings[i][random() % digits] = (random() % 10) + '0';
1737
1738           strcpy (b->code, st->strings[i]);
1739           processUpcEan (st, b->code, b->bitmap);
1740         }
1741 }
1742
1743
1744 /* update the model for one iteration.
1745    This one draws a clock.  By jwz.  */
1746 static void updateClock (struct state *st)
1747 {
1748   Barcode *b = &st->barcodes[0];
1749   int BW = 76 /* BARCODE_WIDTH  */;
1750   int BH = BARCODE_HEIGHT;
1751   int mag_x, mag_y;
1752   int i;
1753   time_t now = time ((time_t *) 0);
1754   struct tm *tm = localtime (&now);
1755   XWindowAttributes xgwa;
1756   int ow = st->windowWidth;
1757   int oh = st->windowHeight;
1758
1759   XGetWindowAttributes (st->dpy, st->window, &xgwa);
1760   st->windowWidth = xgwa.width;
1761   st->windowHeight = xgwa.height;
1762
1763   mag_x  = st->windowWidth  / BW;
1764   mag_y  = st->windowHeight / BH;
1765
1766   st->barcode_count = 1;
1767
1768   b->mag = (mag_x < mag_y ? mag_x : mag_y);
1769
1770   if (b->mag > MAX_MAG) b->mag = MAX_MAG;
1771   if (b->mag < 1) b->mag = 1;
1772
1773   b->x = (st->windowWidth  - (b->mag * BW      )) / 2;
1774   b->y = (st->windowHeight - (b->mag * (BH + 9))) / 2;
1775   b->pixel = st->fg_pixel;
1776
1777   if (!st->button_down_p)
1778     sprintf (b->code, "0%02d%02d%02d?:",
1779              (st->mode == BC_CLOCK24
1780               ? tm->tm_hour
1781               : (tm->tm_hour > 12
1782                  ? tm->tm_hour - 12
1783                  : (tm->tm_hour == 0
1784                     ? 12
1785                     : tm->tm_hour))),
1786              tm->tm_min,
1787              tm->tm_sec);
1788   else
1789     sprintf (b->code, "0%02d%02d%02d?:",
1790              tm->tm_year % 100, tm->tm_mon+1, tm->tm_mday);
1791
1792   {
1793     int vstart = 9;
1794     int hh = BH + vstart;
1795     char expandedDigits[13];
1796
1797     expandedDigits[0] = '\0';
1798
1799     expandToUpcADigits (b->code, expandedDigits);
1800     if (expandedDigits[0] != '\0')
1801       b->code[7] = expandedDigits[11];
1802
1803     bitmapClear (st->theBitmap);
1804     drawUpcEBars (st, st->theBitmap, b->code, 6, 9, 59, 65);
1805     for (i = 0; i < 6; i++)
1806       {
1807         int off = (i < 2 ? 0 :
1808                    i < 4 ? 4 :
1809                    8);
1810         drawDigitChar (st, st->theBitmap, 11 + i*7 + off, hh - 16, b->code[i+1]);
1811       }
1812
1813     if (!st->button_down_p)
1814       {
1815 #if 0
1816         char *days[] = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
1817         char *s = days[tm->tm_wday];
1818         bitmapDrawString5x8 (st->theBitmap, (BW - strlen (s)*5) / 2, 0, s);
1819 #endif
1820         drawDigitChar (st, st->theBitmap,  0, hh - 23, (tm->tm_hour < 12 ? 'A' : 'P'));
1821         drawDigitChar (st, st->theBitmap, 68, hh - 23, 'M');
1822       }
1823     else
1824       {
1825         char s[20];
1826         sprintf (s, "%03d", tm->tm_yday);
1827         bitmapDrawString5x8 (st->theBitmap, (BW - strlen (s)*5) / 2, 0, s);
1828       }
1829   }
1830
1831   bitmapScale (b->bitmap, st->theBitmap, b->mag);
1832
1833   if (ow != st->windowWidth || oh != st->windowHeight)
1834     XClearWindow (st->dpy, st->window);
1835 }
1836
1837
1838
1839 /* render and dpy the current model */
1840 static void renderFrame (struct state *st)
1841 {
1842     int i;
1843
1844     for (i = 0; i < st->barcode_count; i++)
1845     {
1846         Barcode *barcode = &st->barcodes[i];
1847
1848         if (barcode->x > st->windowWidth) {
1849             break;
1850         }
1851
1852         /* bitmapScale (st->theBitmap, barcode->bitmap, barcode->mag);*/
1853         st->theImage->data = barcode->bitmap->buf;
1854
1855         XSetForeground (st->dpy, st->theGC, barcode->pixel);
1856         XPutImage (st->dpy, st->window, st->theGC, st->theImage, 
1857                    0, 0, barcode->x, barcode->y, 
1858                    BARCODE_WIDTH * barcode->mag,
1859                    BARCODE_HEIGHT * barcode->mag);
1860     }
1861 }
1862
1863 /* do one iteration */
1864 static unsigned long
1865 barcode_draw (Display *dpy, Window win, void *closure)
1866 {
1867   struct state *st = (struct state *) closure;
1868     if (st->mode == BC_SCROLL)
1869       scrollModel (st);
1870     else if (st->mode == BC_GRID)
1871       updateGrid (st);
1872     else if (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24)
1873       updateClock (st);
1874     else
1875       abort();
1876
1877     renderFrame (st);
1878
1879     return st->delay;
1880 }
1881
1882
1883 static Bool
1884 barcode_event (Display *dpy, Window window, void *closure, XEvent *event)
1885 {
1886   struct state *st = (struct state *) closure;
1887   int clockp = (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24);
1888   if (clockp && event->xany.type == ButtonPress) {
1889     st->button_down_p = True;
1890     return True;
1891   } else if (clockp && event->xany.type == ButtonRelease) {
1892     st->button_down_p = False;
1893     return True;
1894   } else
1895     return False;
1896 }
1897
1898 static void
1899 barcode_reshape (Display *dpy, Window window, void *closure, 
1900                  unsigned int w, unsigned int h)
1901 {
1902   struct state *st = (struct state *) closure;
1903   st->windowWidth = w;
1904   st->windowHeight = h;
1905 }
1906
1907 static void
1908 barcode_free (Display *dpy, Window window, void *closure)
1909 {
1910 }
1911
1912
1913 /* main and options and stuff */
1914
1915 static const char *barcode_defaults [] = {
1916     ".background:       black",
1917     ".foreground:       green",
1918     "*fpsSolid:         true",
1919     "*delay:            10000",
1920     "*mode:             scroll",
1921     0
1922 };
1923
1924 static XrmOptionDescRec barcode_options [] = {
1925   { "-delay",            ".delay",          XrmoptionSepArg, 0 },
1926   { "-mode",             ".mode",           XrmoptionSepArg, 0 },
1927   { "-scroll",           ".mode",           XrmoptionNoArg, "scroll"  },
1928   { "-grid",             ".mode",           XrmoptionNoArg, "grid"    },
1929   { "-clock",            ".mode",           XrmoptionNoArg, "clock"   },
1930   { "-clock12",          ".mode",           XrmoptionNoArg, "clock12" },
1931   { "-clock24",          ".mode",           XrmoptionNoArg, "clock24" },
1932   { 0, 0, 0, 0 }
1933 };
1934
1935 /* initialize the user-specifiable params */
1936 static void initParams (struct state *st)
1937 {
1938     int problems = 0;
1939     char *s;
1940
1941     st->delay = get_integer_resource (st->dpy, "delay", "Delay");
1942     if (st->delay < 0)
1943     {
1944         fprintf (stderr, "%s: delay must be at least 0\n", progname);
1945         problems = 1;
1946     }
1947
1948     s = get_string_resource (st->dpy, "mode", "Mode");
1949     if (!s || !*s || !strcasecmp (s, "scroll"))
1950       st->mode = BC_SCROLL;
1951     else if (!strcasecmp (s, "grid"))
1952       st->mode = BC_GRID;
1953     else if (!strcasecmp (s, "clock") ||
1954              !strcasecmp (s, "clock12"))
1955       st->mode = BC_CLOCK12;
1956     else if (!strcasecmp (s, "clock24"))
1957       st->mode = BC_CLOCK24;
1958     else
1959       {
1960         fprintf (stderr, "%s: unknown mode \"%s\"\n", progname, s);
1961         problems = 1;
1962       }
1963     free (s);
1964
1965     if (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24)
1966       st->delay = 10000;  /* only update every 1/10th second */
1967
1968     if (problems)
1969     {
1970         exit (1);
1971     }
1972 }
1973
1974 static void *
1975 barcode_init (Display *dpy, Window win)
1976 {
1977   struct state *st = (struct state *) calloc (1, sizeof(*st));
1978   st->dpy = dpy;
1979   st->window = win;
1980
1981   initParams (st);
1982   setup (st);
1983   setupModel (st);
1984   return st;
1985 }
1986
1987
1988 XSCREENSAVER_MODULE ("Barcode", barcode)