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