1 /* barcode, draw some barcodes
2 * by Dan Bornstein, danfuzz@milk.com
3 * Copyright (c) 2003 Dan Bornstein. All rights reserved.
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
13 * See the included man page for more details.
21 #include "screenhack.h"
22 #include <X11/Xutil.h>
26 /* parameters that are user configurable */
28 /* delay (usec) between iterations */
35 /* non-user-modifiable immutable definitions */
39 /* random float in the range (0..1) */
40 #define RAND_FLOAT_01 \
41 (((FLOAT) ((random() >> 8) & 0xffff)) / ((FLOAT) 0x10000))
43 #define BARCODE_WIDTH (164)
44 #define BARCODE_HEIGHT (69)
47 /* width and height of the window */
48 static int windowWidth;
49 static int windowHeight;
51 static Display *display; /* the display to draw on */
52 static Window window; /* the window to draw on */
53 static Visual *visual; /* the visual to use */
54 static Screen *screen; /* the screen to draw on */
55 static Colormap cmap; /* the colormap of the window */
57 static GC theGC; /* GC for drawing */
61 /* simple bitmap structure */
78 int x; /* x coordinate of the left of the barcode */
79 int y; /* y coordinate of the left of the barcode */
80 int mag; /* magnfication factor */
81 Bitmap *bitmap; /* the bitmap */
82 char code[128]; /* the barcode string */
83 unsigned long pixel; /* the color */
87 static Barcode *barcodes; /* array of barcodes */
88 static int barcode_count; /* how many barcodes are currently active */
89 static int barcode_max; /* the maximum number of active barcodes */
91 static XImage *theImage; /* ginormo image for drawing */
92 static Bitmap *theBitmap; /* ginormo bitmap for drawing */
94 /* a bunch of words */
95 static char *words[] =
337 #define WORD_COUNT (sizeof(words) / sizeof(char *))
341 /* ----------------------------------------------------------------------------
342 * bitmap manipulation
345 /* construct a new bitmap */
346 Bitmap *makeBitmap (int width, int height)
348 Bitmap *result = malloc (sizeof (Bitmap));
349 result->width = width;
350 result->height = height;
351 result->widthBytes = (width + 7) / 8;
352 result->buf = calloc (1, height * result->widthBytes);
357 void bitmapClear (Bitmap *b)
359 memset (b->buf, 0, b->widthBytes * b->height);
363 void bitmapFree (Bitmap *b)
369 /* get the byte value at the given byte-offset coordinates in the given
371 int bitmapGetByte (Bitmap *b, int xByte, int y)
374 (xByte >= b->widthBytes) ||
378 /* out-of-range get returns 0 */
382 return b->buf[b->widthBytes * y + xByte];
385 /* get the bit value at the given coordinates in the given bitmap */
386 int bitmapGet (Bitmap *b, int x, int y)
390 int byteValue = bitmapGetByte (b, xbyte, y);
392 return (byteValue & (1 << xbit)) >> xbit;
395 /* set the bit value at the given coordinates in the given bitmap */
396 void bitmapSet (Bitmap *b, int x, int y, int value)
406 /* ignore out-of-range set */
412 b->buf[b->widthBytes * y + xbyte] |= 1 << xbit;
416 b->buf[b->widthBytes * y + xbyte] &= ~(1 << xbit);
420 /* copy the given rectangle to the given destination from the given source. */
421 void bitmapCopyRect (Bitmap *dest, int dx, int dy,
422 Bitmap *src, int sx, int sy, int width, int height)
426 for (y = 0; y < height; y++)
428 for (x = 0; x < width; x++)
430 bitmapSet (dest, x + dx, y + dy, bitmapGet (src, x + sx, y + sy));
435 /* draw a vertical line in the given bitmap */
436 void bitmapVlin (Bitmap *b, int x, int y1, int y2)
440 bitmapSet (b, x, y1, 1);
445 /* scale a bitmap into another bitmap */
446 void bitmapScale (Bitmap *dest, Bitmap *src, int mag)
450 for (y = 0; y < src->height; y++)
452 for (x = 0; x < src->width; x++)
454 int v = bitmapGet (src, x, y);
455 for (x2 = 0; x2 < mag; x2++)
457 for (y2 = 0; y2 < mag; y2++)
459 bitmapSet (dest, x * mag + x2, y * mag + y2, v);
467 /* ----------------------------------------------------------------------------
468 * character generation
471 static unsigned char font5x8Buf[] =
473 0x1e, 0x01, 0x06, 0x01, 0x1e, 0x00, 0x1e, 0x01, 0x06, 0x01, 0x1e, 0x00,
474 0x1e, 0x01, 0x1e, 0x01, 0x1e, 0x00, 0x01, 0x00, 0x1f, 0x08, 0x04, 0x08,
475 0x1f, 0x00, 0x11, 0x1f, 0x11, 0x00, 0x1f, 0x01, 0x01, 0x00, 0x1f, 0x04,
476 0x0a, 0x11, 0x00, 0x01, 0x00, 0x0e, 0x11, 0x11, 0x00, 0x0e, 0x11, 0x11,
477 0x0e, 0x00, 0x1f, 0x08, 0x04, 0x08, 0x1f, 0x00, 0x44, 0x41, 0x4e, 0x20,
478 0x42, 0x4f, 0x52, 0x4e, 0x53, 0x54, 0x45, 0x49, 0x4e, 0x21, 0x21, 0x00,
479 0x66, 0x6e, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
480 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
481 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
482 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
483 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
484 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
485 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
486 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
487 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
488 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
489 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
490 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
491 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
492 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
493 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
494 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
495 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x05, 0x05, 0x00,
496 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x00,
497 0x02, 0x0f, 0x01, 0x0f, 0x08, 0x0f, 0x04, 0x00, 0x0b, 0x0b, 0x08, 0x06,
498 0x01, 0x0d, 0x0d, 0x00, 0x03, 0x05, 0x02, 0x05, 0x0d, 0x05, 0x0b, 0x00,
499 0x04, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x02,
500 0x02, 0x02, 0x04, 0x00, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x00,
501 0x00, 0x09, 0x06, 0x0f, 0x06, 0x09, 0x00, 0x00, 0x00, 0x02, 0x02, 0x07,
502 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x06, 0x00,
503 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
504 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x04, 0x06, 0x02, 0x01, 0x01, 0x00,
505 0x0f, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x06, 0x04, 0x04, 0x04,
506 0x04, 0x04, 0x0f, 0x00, 0x0f, 0x09, 0x08, 0x0f, 0x01, 0x09, 0x0f, 0x00,
507 0x0f, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x0f, 0x00, 0x09, 0x09, 0x09, 0x0f,
508 0x08, 0x08, 0x08, 0x00, 0x0f, 0x09, 0x01, 0x0f, 0x08, 0x09, 0x0f, 0x00,
509 0x03, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0c,
510 0x04, 0x04, 0x04, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x0f, 0x00,
511 0x0f, 0x09, 0x09, 0x0f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00,
512 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x04, 0x06, 0x00,
513 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x0f, 0x00,
514 0x0f, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x04, 0x02, 0x01, 0x00,
515 0x0f, 0x09, 0x08, 0x0e, 0x02, 0x00, 0x02, 0x00, 0x0f, 0x09, 0x0d, 0x0d,
516 0x0d, 0x01, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x09, 0x00,
517 0x07, 0x09, 0x09, 0x07, 0x09, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x01, 0x01,
518 0x01, 0x01, 0x0f, 0x00, 0x07, 0x09, 0x09, 0x09, 0x09, 0x09, 0x07, 0x00,
519 0x0f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x0f, 0x00, 0x0f, 0x01, 0x01, 0x0f,
520 0x01, 0x01, 0x01, 0x00, 0x0f, 0x01, 0x01, 0x0d, 0x09, 0x09, 0x0f, 0x00,
521 0x09, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x09, 0x00, 0x07, 0x02, 0x02, 0x02,
522 0x02, 0x02, 0x07, 0x00, 0x0e, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x00,
523 0x09, 0x09, 0x09, 0x07, 0x09, 0x09, 0x09, 0x00, 0x01, 0x01, 0x01, 0x01,
524 0x01, 0x01, 0x0f, 0x00, 0x09, 0x0f, 0x0f, 0x0f, 0x09, 0x09, 0x09, 0x00,
525 0x09, 0x0b, 0x0d, 0x09, 0x09, 0x09, 0x09, 0x00, 0x0f, 0x09, 0x09, 0x09,
526 0x09, 0x09, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x01, 0x01, 0x01, 0x00,
527 0x0f, 0x09, 0x09, 0x09, 0x0b, 0x05, 0x0b, 0x00, 0x07, 0x09, 0x09, 0x07,
528 0x09, 0x09, 0x09, 0x00, 0x0f, 0x01, 0x01, 0x0f, 0x08, 0x08, 0x0f, 0x00,
529 0x0f, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x09, 0x09, 0x09, 0x09,
530 0x09, 0x09, 0x0f, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x05, 0x02, 0x00,
531 0x09, 0x09, 0x09, 0x09, 0x0f, 0x0f, 0x09, 0x00, 0x09, 0x09, 0x05, 0x06,
532 0x0a, 0x09, 0x09, 0x00, 0x09, 0x09, 0x09, 0x0f, 0x08, 0x08, 0x0f, 0x00,
533 0x0f, 0x08, 0x08, 0x06, 0x01, 0x01, 0x0f, 0x00, 0x0e, 0x02, 0x02, 0x02,
534 0x02, 0x02, 0x0e, 0x00, 0x01, 0x01, 0x02, 0x06, 0x04, 0x08, 0x08, 0x00,
535 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x00, 0x02, 0x05, 0x05, 0x00,
536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
537 0x02, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08,
538 0x0f, 0x09, 0x0f, 0x00, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x09, 0x0f, 0x00,
539 0x00, 0x00, 0x0f, 0x01, 0x01, 0x01, 0x0f, 0x00, 0x08, 0x08, 0x0f, 0x09,
540 0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x09, 0x0f, 0x01, 0x0f, 0x00,
541 0x0e, 0x02, 0x0f, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x09,
542 0x09, 0x0f, 0x08, 0x0c, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x09, 0x09, 0x00,
543 0x02, 0x00, 0x03, 0x02, 0x02, 0x02, 0x07, 0x00, 0x04, 0x00, 0x04, 0x04,
544 0x04, 0x04, 0x05, 0x07, 0x01, 0x01, 0x09, 0x05, 0x03, 0x05, 0x09, 0x00,
545 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x00, 0x00, 0x09, 0x0f,
546 0x0f, 0x09, 0x09, 0x00, 0x00, 0x00, 0x0f, 0x09, 0x09, 0x09, 0x09, 0x00,
547 0x00, 0x00, 0x0f, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x09,
548 0x09, 0x0f, 0x01, 0x01, 0x00, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x08, 0x08,
549 0x00, 0x00, 0x0f, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x01,
550 0x0f, 0x08, 0x0f, 0x00, 0x00, 0x02, 0x0f, 0x02, 0x02, 0x02, 0x0e, 0x00,
551 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x09, 0x09,
552 0x09, 0x05, 0x02, 0x00, 0x00, 0x00, 0x09, 0x09, 0x0f, 0x0f, 0x09, 0x00,
553 0x00, 0x00, 0x09, 0x09, 0x06, 0x09, 0x09, 0x00, 0x00, 0x00, 0x09, 0x09,
554 0x09, 0x0f, 0x08, 0x0c, 0x00, 0x00, 0x0f, 0x08, 0x06, 0x01, 0x0f, 0x00,
555 0x08, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08, 0x00, 0x02, 0x02, 0x02, 0x02,
556 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x04, 0x02, 0x02, 0x01, 0x00,
557 0x00, 0x0a, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
558 0x0f, 0x0f, 0x0f, 0x00
561 static Bitmap font5x8 = { 8, 1024, 1, font5x8Buf };
563 /* draw the given 5x8 character at the given coordinates */
564 void bitmapDrawChar5x8 (Bitmap *b, int x, int y, char c)
566 bitmapCopyRect (b, x, y, &font5x8, 0, c * 8, 5, 8);
569 /* draw a string of 5x8 characters at the given coordinates */
570 void bitmapDrawString5x8 (Bitmap *b, int x, int y, char *str)
589 bitmapDrawChar5x8 (b, x, y, c);
598 /* ----------------------------------------------------------------------------
599 * upc/ean symbologies
602 /* A quick lesson in UPC and EAN barcodes:
604 * Each digit consists of 2 bars and 2 spaces, taking a total width of 7
605 * times the width of the thinnest possible bar or space. There are three
606 * different possible representations for each digit, used depending on
607 * what side of a two-sided barcode the digit is used on, and to encode
608 * checksum or other information in some cases. The three forms are
609 * related. Taking as the "base" form the pattern as seen on the right-hand
610 * side of a UPC-A barcode, the other forms are the inverse of the base
611 * (that is, bar becomes space and vice versa) and the mirror image of the
612 * base. Still confused? Here's a complete table, where 0 means space and 1
615 * Left-A Left-B Right
616 * ------- ------- -------
617 * 0 0001101 0100111 1110010
618 * 1 0011001 0110011 1100110
619 * 2 0010011 0011011 1101100
620 * 3 0111101 0100001 1000010
621 * 4 0100011 0011101 1011100
622 * 5 0110001 0111001 1001110
623 * 6 0101111 0000101 1010000
624 * 7 0111011 0010001 1000100
625 * 8 0110111 0001001 1001000
626 * 9 0001011 0010111 1110100
628 * A UPC-A barcode consists of 6 patterns from Left-A on the left-hand side,
629 * 6 patterns from Right on the right-hand side, a guard pattern of 01010
630 * in the middle, and a guard pattern of 101 on each end. The 12th digit
631 * checksum is calculated as follows: Take the 1st, 3rd, ... 11th digits,
632 * sum them and multiplying by 3, and add that to the sum of the other digits.
633 * Subtract the final digit from 10, and that is the checksum digit. (If
634 * the last digit of the sum is 0, then the check digit is 0.)
636 * An EAN-13 barcode is just like a UPC-A barcode, except that the characters
637 * on the left-hand side have a pattern of Left-A and Left-B that encodes
638 * an extra first digit. Note that an EAN-13 barcode with the first digit
639 * of 0 is exactly the same as the UPC-A barcode of the rightmost 12 digits.
640 * The patterns to encode the first digit are as follows:
657 * The checksum for EAN-13 is just like UPC-A, except the 2nd, 4th, ... 12th
658 * digits are multiplied by 3 instead of the other way around.
660 * An EAN-8 barcode is just like a UPC-A barcode, except there are only 4
661 * digits in each half. Unlike EAN-13, there's no nonsense about different
662 * left-hand side patterns, either.
664 * A UPC-E barcode contains 6 explicit characters between a guard of 101
665 * on the left and 010101 on the right. The explicit characters are the
666 * middle six characters of the code. The first and last characters are
667 * encoded in the parity pattern of the six characters. There are two
668 * sets of parity patterns, one to use if the first digit of the number
669 * is 0, and another if it is 1. (UPC-E barcodes may only start with a 0
670 * or 1.) The patterns are as follows:
672 * First digit 0 First digit 1
673 * Explicit Digit Explicit Digit
675 * 1 2 3 4 5 6 1 2 3 4 5 6
676 * - - - - - - - - - - - -
677 * 0 b b b a a a a a a b b b
678 * 1 b b a b a a a a b a b b
679 * 2 b b a a b a a a b b a b
680 * 3 b b a a a b a a b b b a
681 * 4 b a b b a a a b a a b b
682 * 5 b a a b b a a b b a a b
683 * 6 b a a a b b a b b b a a
684 * 7 b a b a b a a b a b a b
685 * 8 b a b a a b a b a b b a
686 * 9 b a a b a b a b b a b a
688 * (Note that the two sets are the complements of each other. Also note
689 * that the first digit 1 patterns are mostly the same as the EAN-13
690 * first digit patterns.) The UPC-E check digit (the final digit encoded in
691 * the parity pattern) is the same as the UPC-A check digit for the
692 * expanded form of the UPC-E number. The expanstion is as follows, based
693 * on the last explicit digit (the second to last digit) in the encoded
697 * UPC-E form UPC-A form
698 * ---------- -------------
699 * XABCDE0Y XAB00000CDEY
700 * XABCDE1Y XAB10000CDEY
701 * XABCDE2Y XAB20000CDEY
702 * XABCDE3Y XABC00000DEY
703 * XABCDE4Y XABCD00000EY
704 * XABCDE5Y XABCDE00005Y
705 * XABCDE6Y XABCDE00006Y
706 * XABCDE7Y XABCDE00007Y
707 * XABCDE8Y XABCDE00008Y
708 * XABCDE9Y XABCDE00009Y
710 * All UPC/EAN barcodes may have an additional 2- or 5-digit supplemental
711 * code just to the right of the main barcode. The supplement starts about
712 * one digit-length (that is about 7 times the width of the thinnest bar)
713 * to the right of the main code, beginning with the guard pattern 1011.
714 * After that comes each digit, with a guard pattern of 01 between each,
715 * but not at the end. The digits are encoded using the left A and B
716 * characters to encode a parity pattern.
718 * For 2-digit supplements, the parity pattern is determined by the
719 * lower two bits of the numeric value of the code (e.g., 42 would use
722 * Lower 2 bits Parity Pattern
723 * ------------ --------------
729 * For 5-digit supplements, the parity pattern is calculated in a similar
730 * manner to check digit calculation: The first, third, and fifth digits
731 * are summed and multiplied by 3; the second and fourth digits are summed
732 * and multiplied by nine; the parity digit is the sum of those two numbers,
733 * modulo 10. The parity pattern is then the last five patterns from the
734 * UPC-E final digit 0 table for the corresponding digit.
737 /* enum to indicate which pattern set to use */
740 UPC_LEFT_A, UPC_LEFT_B, UPC_RIGHT
744 /* the Left A patterns */
745 unsigned int upcLeftA[] = {
746 0x0d, 0x19, 0x13, 0x3d, 0x23, 0x31, 0x2f, 0x3b, 0x37, 0x0b
749 /* the Left B patterns */
750 unsigned int upcLeftB[] = {
751 0x27, 0x33, 0x1b, 0x21, 0x1d, 0x39, 0x05, 0x11, 0x09, 0x17
754 /* the Right patterns */
755 unsigned int upcRight[] = {
756 0x72, 0x66, 0x6c, 0x42, 0x5c, 0x4e, 0x50, 0x44, 0x48, 0x74
759 /* the EAN-13 first-digit patterns */
760 unsigned int ean13FirstDigit[] = {
761 0x00, 0x0b, 0x0d, 0x0e, 0x13, 0x19, 0x1c, 0x15, 0x16, 0x1a
764 /* the UPC-E last-digit patterns for first digit 0 (complement for
765 * digit 1); also used for 5-digit supplemental check patterns */
766 unsigned int upcELastDigit[] = {
767 0x38, 0x34, 0x32, 0x31, 0x2c, 0x26, 0x23, 0x2a, 0x29, 0x25
770 /* turn a character into an int representing its digit value; return
771 * 0 for things not in the range '0'-'9' */
772 int charToDigit (char c)
774 if ((c >= '0') && (c <= '9'))
784 /* draw the given digit character at the given coordinates; a '0' is
785 * used in place of any non-digit character */
786 void drawDigitChar (Bitmap *b, int x, int y, char c)
788 if ((c < '0') || (c > '9'))
793 bitmapDrawChar5x8 (b, x, y, c);
796 /* draw a upc/ean digit at the given coordinates */
797 void drawUpcEanDigit (Bitmap *upcBitmap, int x, int y1, int y2, char n,
807 bits = upcLeftA[(int) n];
810 bits = upcLeftB[(int) n];
812 default /* case UPC_RIGHT */:
813 bits = upcRight[(int) n];
817 for (i = 6; i >=0; i--)
821 bitmapVlin (upcBitmap, x, y1, y2);
827 /* report the width of the given supplemental code or 0 if it is a bad
829 int upcEanSupplementWidth (char *digits)
831 switch (strlen (digits))
833 case 2: return 28; /* 8 + 4 + 2*7 + 1*2 */
834 case 5: return 55; /* 8 + 4 + 5*7 + 4*2 */
839 /* draw the given supplemental barcode, including the textual digits */
840 void drawUpcEanSupplementalBars (Bitmap *upcBitmap, char *digits,
841 int x, int y, int y2, int textAbove)
843 int len = strlen (digits);
860 x += 8; /* skip the space between the main and supplemental */
867 parity = (charToDigit (digits[0]) * 10 +
868 charToDigit (digits[1])) & 0x3;
875 ((charToDigit (digits[0]) + charToDigit (digits[2]) +
876 charToDigit (digits[4])) * 3
877 + (charToDigit (digits[1]) + charToDigit (digits[3])) * 9)
879 parity = upcELastDigit[parity];
884 printf("Bad supplement\n");
891 bitmapVlin (upcBitmap, x, y, y2);
892 bitmapVlin (upcBitmap, x + 2, y, y2);
893 bitmapVlin (upcBitmap, x + 3, y, y2);
895 for (i = 0; i < len; i++)
898 (parity & (1 << (len - 1 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
899 int baseX = x + 2 + i * 9;
901 /* separator / end of header */
904 bitmapVlin (upcBitmap, baseX, y, y2);
906 bitmapVlin (upcBitmap, baseX + 1, y, y2);
908 drawUpcEanDigit (upcBitmap,
915 drawDigitChar (upcBitmap, textX + i*6, textY, digits[i]);
919 /* draw the actual barcode part of a UPC-A barcode */
920 void drawUpcABars (Bitmap *upcBitmap, char *digits, int x, int y,
921 int barY2, int guardY2)
926 bitmapVlin (upcBitmap, x, y, guardY2);
927 bitmapVlin (upcBitmap, x + 2, y, guardY2);
930 bitmapVlin (upcBitmap, x + 46, y, guardY2);
931 bitmapVlin (upcBitmap, x + 48, y, guardY2);
934 bitmapVlin (upcBitmap, x + 92, y, guardY2);
935 bitmapVlin (upcBitmap, x + 94, y, guardY2);
937 for (i = 0; i < 6; i++)
939 drawUpcEanDigit (upcBitmap,
942 (i == 0) ? guardY2 : barY2,
945 drawUpcEanDigit (upcBitmap,
948 (i == 5) ? guardY2 : barY2,
954 /* make and return a full-height UPC-A barcode */
955 int makeUpcAFull (Bitmap *dest, char *digits, int y)
957 static int baseWidth = 108;
958 static int baseHeight = 60;
960 int height = baseHeight + y;
964 drawUpcABars (dest, digits, 6, y, height - 10, height - 4);
966 drawDigitChar (dest, 0, height - 14, digits[0]);
968 for (i = 0; i < 5; i++)
970 drawDigitChar (dest, 18 + i*7, height - 7, digits[i+1]);
971 drawDigitChar (dest, 57 + i*7, height - 7, digits[i+6]);
974 drawDigitChar (dest, 103, height - 14, digits[11]);
979 /* make and return a UPC-A barcode */
980 int makeUpcA (Bitmap *dest, char *digits, int y)
983 unsigned int mul = 3;
984 unsigned int sum = 0;
986 for (i = 0; i < 11; i++)
988 sum += charToDigit (digits[i]) * mul;
992 if (digits[11] == '?')
994 digits[11] = ((10 - (sum % 10)) % 10) + '0';
997 return makeUpcAFull (dest, digits, y);
1000 /* draw the actual barcode part of a UPC-E barcode */
1001 void drawUpcEBars (Bitmap *upcBitmap, char *digits, int x, int y,
1002 int barY2, int guardY2)
1005 int parityPattern = upcELastDigit[charToDigit(digits[7])];
1007 if (digits[0] == '1')
1009 parityPattern = ~parityPattern;
1013 bitmapVlin (upcBitmap, x, y, guardY2);
1014 bitmapVlin (upcBitmap, x + 2, y, guardY2);
1017 bitmapVlin (upcBitmap, x + 46, y, guardY2);
1018 bitmapVlin (upcBitmap, x + 48, y, guardY2);
1019 bitmapVlin (upcBitmap, x + 50, y, guardY2);
1021 for (i = 0; i < 6; i++)
1024 (parityPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
1026 drawUpcEanDigit (upcBitmap,
1035 /* make and return a full-height UPC-E barcode */
1036 int makeUpcEFull (Bitmap *dest, char *digits, int y)
1038 static int baseWidth = 64;
1039 static int baseHeight = 60;
1041 int height = baseHeight + y;
1045 drawUpcEBars (dest, digits, 6, y, height - 10, height - 4);
1047 drawDigitChar (dest, 0, height - 14, digits[0]);
1049 for (i = 0; i < 6; i++)
1051 drawDigitChar (dest, 11 + i*7, height - 7, digits[i+1]);
1054 drawDigitChar (dest, 59, height - 14, digits[7]);
1059 /* expand 8 UPC-E digits into a UPC-A number, storing into the given result
1060 * array, or just store '\0' into the first element, if the form factor
1061 * is incorrect; this will also calculate the check digit, if it is
1062 * specified as '?' */
1063 void expandToUpcADigits (char *compressed, char *expanded)
1067 if ((compressed[0] != '0') && (compressed[0] != '1'))
1072 expanded[0] = compressed[0];
1075 expanded[11] = compressed[7];
1077 switch (compressed[6])
1083 expanded[1] = compressed[1];
1084 expanded[2] = compressed[2];
1085 expanded[3] = compressed[6];
1088 expanded[8] = compressed[3];
1089 expanded[9] = compressed[4];
1090 expanded[10] = compressed[5];
1095 expanded[1] = compressed[1];
1096 expanded[2] = compressed[2];
1097 expanded[3] = compressed[3];
1101 expanded[9] = compressed[4];
1102 expanded[10] = compressed[5];
1107 expanded[1] = compressed[1];
1108 expanded[2] = compressed[2];
1109 expanded[3] = compressed[3];
1110 expanded[4] = compressed[4];
1114 expanded[10] = compressed[5];
1119 expanded[1] = compressed[1];
1120 expanded[2] = compressed[2];
1121 expanded[3] = compressed[3];
1122 expanded[4] = compressed[4];
1123 expanded[5] = compressed[5];
1126 expanded[10] = compressed[6];
1131 if (expanded[11] == '?')
1133 unsigned int mul = 3;
1134 unsigned int sum = 0;
1136 for (i = 0; i < 11; i++)
1138 sum += charToDigit (expanded[i]) * mul;
1142 expanded[11] = ((10 - (sum % 10)) % 10) + '0';
1146 /* make and return a UPC-E barcode */
1147 int makeUpcE (Bitmap *dest, char *digits, int y)
1149 char expandedDigits[13];
1150 char compressedDigits[9];
1152 expandedDigits[0] = '\0';
1153 compressedDigits[0] = '0';
1154 strcpy (compressedDigits + 1, digits);
1156 expandToUpcADigits (compressedDigits, expandedDigits);
1157 if (expandedDigits[0] == '\0')
1162 compressedDigits[7] = expandedDigits[11];
1164 return makeUpcEFull (dest, compressedDigits, y);
1167 /* draw the actual barcode part of a EAN-13 barcode */
1168 void drawEan13Bars (Bitmap *upcBitmap, char *digits, int x, int y,
1169 int barY2, int guardY2)
1172 int leftPattern = ean13FirstDigit[charToDigit (digits[0])];
1175 bitmapVlin (upcBitmap, x, y, guardY2);
1176 bitmapVlin (upcBitmap, x + 2, y, guardY2);
1179 bitmapVlin (upcBitmap, x + 46, y, guardY2);
1180 bitmapVlin (upcBitmap, x + 48, y, guardY2);
1183 bitmapVlin (upcBitmap, x + 92, y, guardY2);
1184 bitmapVlin (upcBitmap, x + 94, y, guardY2);
1186 for (i = 0; i < 6; i++)
1188 UpcSet lset = (leftPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
1190 drawUpcEanDigit (upcBitmap,
1196 drawUpcEanDigit (upcBitmap,
1205 /* make and return a full-height EAN-13 barcode */
1206 int makeEan13Full (Bitmap *dest, char *digits, int y)
1208 static int baseWidth = 102;
1209 static int baseHeight = 60;
1211 int height = baseHeight + y;
1215 drawEan13Bars (dest, digits, 6, y, height - 10, height - 4);
1217 drawDigitChar (dest, 0, height - 7, digits[0]);
1219 for (i = 0; i < 6; i++)
1221 drawDigitChar (dest, 11 + i*7, height - 7, digits[i+1]);
1222 drawDigitChar (dest, 57 + i*7, height - 7, digits[i+7]);
1228 /* make and return an EAN-13 barcode */
1229 int makeEan13 (Bitmap *dest, char *digits, int y)
1232 unsigned int mul = 1;
1233 unsigned int sum = 0;
1235 for (i = 0; i < 12; i++)
1237 sum += charToDigit (digits[i]) * mul;
1241 if (digits[12] == '?')
1243 digits[12] = ((10 - (sum % 10)) % 10) + '0';
1246 return makeEan13Full (dest, digits, y);
1249 /* draw the actual barcode part of an EAN-8 barcode */
1250 void drawEan8Bars (Bitmap *upcBitmap, char *digits, int x, int y,
1251 int barY2, int guardY2)
1256 bitmapVlin (upcBitmap, x, y, guardY2);
1257 bitmapVlin (upcBitmap, x + 2, y, guardY2);
1260 bitmapVlin (upcBitmap, x + 32, y, guardY2);
1261 bitmapVlin (upcBitmap, x + 34, y, guardY2);
1264 bitmapVlin (upcBitmap, x + 64, y, guardY2);
1265 bitmapVlin (upcBitmap, x + 66, y, guardY2);
1267 for (i = 0; i < 4; i++)
1269 drawUpcEanDigit (upcBitmap,
1275 drawUpcEanDigit (upcBitmap,
1284 /* make and return a full-height EAN-8 barcode */
1285 int makeEan8Full (Bitmap *dest, char *digits, int y)
1287 static int baseWidth = 68;
1288 static int baseHeight = 60;
1290 int height = baseHeight + y;
1294 drawEan8Bars (dest, digits, 0, y, height - 10, height - 4);
1296 for (i = 0; i < 4; i++)
1298 drawDigitChar (dest, 5 + i*7, height - 7, digits[i]);
1299 drawDigitChar (dest, 37 + i*7, height - 7, digits[i+4]);
1305 /* make and return an EAN-8 barcode */
1306 int makeEan8 (Bitmap *dest, char *digits, int y)
1309 unsigned int mul = 3;
1310 unsigned int sum = 0;
1312 for (i = 0; i < 7; i++)
1314 sum += charToDigit (digits[i]) * mul;
1318 if (digits[7] == '?')
1320 digits[7] = ((10 - (sum % 10)) % 10) + '0';
1323 return makeEan8Full (dest, digits, y);
1326 /* Dispatch to the right form factor UPC/EAN barcode generator */
1327 void processUpcEan (char *str, Bitmap *dest)
1332 int supDigitCount = 0;
1334 char *banner = NULL;
1339 while ((digitCount < 15) && (supDigitCount < 7))
1342 if (((c >= '0') && (c <= '9')) || (c == '?'))
1346 supDigits[supDigitCount] = *instr;
1351 digits[digitCount] = *instr;
1371 digits[digitCount] = '\0';
1372 supDigits[supDigitCount] = '\0';
1374 if (supDigitCount == 0)
1378 else if ((supDigitCount == 2) || (supDigitCount == 5))
1380 supplement = upcEanSupplementWidth (supDigits);
1384 printf ("Invalid supplement (must be 2 or 5 digits)\n");
1397 width = makeUpcE (dest, digits, vstart);
1402 width = makeEan8 (dest, digits, vstart);
1407 width = makeUpcA (dest, digits, vstart);
1412 width = makeEan13 (dest, digits, vstart);
1417 printf("Bad barcode\n");
1424 drawUpcEanSupplementalBars (dest, supDigits,
1426 vstart + 1, dest->height - 4, 1);
1431 bitmapDrawString5x8 (dest,
1432 (width + supplement -
1433 ((int) strlen (banner) * 5)) / 2,
1441 /* ----------------------------------------------------------------------------
1446 * overall setup stuff
1449 /* set up the system */
1450 static void setup (void)
1452 XWindowAttributes xgwa;
1455 XGetWindowAttributes (display, window, &xgwa);
1457 screen = xgwa.screen;
1458 visual = xgwa.visual;
1459 cmap = xgwa.colormap;
1460 windowWidth = xgwa.width;
1461 windowHeight = xgwa.height;
1463 gcv.background = get_pixel_resource ("background", "Background",
1464 display, xgwa.colormap);
1465 gcv.foreground = get_pixel_resource ("foreground", "Foreground",
1466 display, xgwa.colormap);
1467 theGC = XCreateGC (display, window, GCForeground|GCBackground, &gcv);
1469 theBitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG, BARCODE_HEIGHT * MAX_MAG);
1470 theImage = XCreateImage(display, visual, 1, XYBitmap, 0, theBitmap->buf,
1471 theBitmap->width, theBitmap->height, 8,
1472 theBitmap->widthBytes);
1481 /* set up the model */
1482 static void setupModel (void)
1488 barcodes = malloc (sizeof (Barcode) * barcode_max);
1490 for (i = 0; i < barcode_max; i++)
1492 barcodes[i].bitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG,
1493 BARCODE_HEIGHT * MAX_MAG);
1497 /* make a new barcode string */
1498 static void makeBarcodeString (char *str)
1502 switch ((int) (RAND_FLOAT_01 * 4))
1504 case 0: dig = 6; break;
1505 case 1: dig = 7; break;
1506 case 2: dig = 11; break;
1507 default: dig = 12; break;
1510 for (i = 0; i < dig; i++)
1512 str[i] = RAND_FLOAT_01 * 10 + '0';
1518 switch ((int) (RAND_FLOAT_01 * 3))
1520 case 0: dig = 0; break;
1521 case 1: dig = 2; break;
1522 default: dig = 5; break;
1531 str[i] = RAND_FLOAT_01 * 10 + '0';
1540 strcpy(&str[i], words[(int) (RAND_FLOAT_01 * WORD_COUNT)]);
1543 /* update the model for one iteration */
1544 static void scrollModel (void)
1548 for (i = 0; i < barcode_count; i++)
1550 Barcode *b = &barcodes[i];
1552 if ((b->x + BARCODE_WIDTH * b->mag) < 0)
1554 /* fell off the edge */
1555 if (i != (barcode_count - 1)) {
1556 Bitmap *oldb = b->bitmap;
1557 memmove (b, b + 1, (barcode_count - i - 1) * sizeof (Barcode));
1558 barcodes[barcode_count - 1].bitmap = oldb;
1560 XFreeColors (display, cmap, &b->pixel, 1, 0);
1568 while (barcode_count < barcode_max)
1570 Barcode *barcode = &barcodes[barcode_count];
1571 barcode->x = (barcode_count == 0) ?
1573 (barcodes[barcode_count - 1].x +
1574 barcodes[barcode_count - 1].mag * BARCODE_WIDTH);
1575 barcode->x += RAND_FLOAT_01 * 100;
1576 barcode->mag = RAND_FLOAT_01 * MAX_MAG;
1578 RAND_FLOAT_01 * (windowHeight - BARCODE_HEIGHT * barcode->mag);
1583 makeBarcodeString(barcode->code);
1584 processUpcEan (barcode->code, theBitmap);
1585 bitmapScale (barcode->bitmap, theBitmap, barcode->mag);
1590 for (i = 0; i < 100; i++)
1592 hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1593 ok = XAllocColor (display, cmap, &c);
1598 c.red = c.green = c.blue = 0xFFFF;
1599 if (!XAllocColor (display, cmap, &c))
1602 barcode->pixel = c.pixel;
1609 /* update the model for one iteration */
1610 static void updateGrid (void)
1613 static int grid_w = 0;
1614 static int grid_h = 0;
1616 static unsigned long pixel;
1617 static int alloced_p = 0;
1619 static char *strings[200] = { 0, };
1621 if (grid_w == 0 || grid_h == 0 ||
1622 (! (random() % 400)))
1624 XClearWindow (display, window);
1625 grid_w = 1 + (random() % 3);
1626 grid_h = 1 + (random() % 4);
1629 if (!alloced_p || (! (random() % 100)))
1632 hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1634 XFreeColors (display, cmap, &pixel, 1, 0);
1635 XAllocColor (display, cmap, &c);
1640 barcode_count = grid_w * grid_h;
1641 if (barcode_count > barcode_max) abort();
1643 for (i = 0; i < barcode_max; i++)
1645 Barcode *b = &barcodes[i];
1646 b->x = b->y = 999999;
1650 for (y = 0; y < grid_h; y++)
1651 for (x = 0; x < grid_w; x++, i++)
1653 Barcode *b = &barcodes[i];
1656 int cell_w = (windowWidth / grid_w);
1657 int cell_h = (windowHeight / grid_h);
1658 int mag_x = cell_w / BARCODE_WIDTH;
1659 int mag_y = cell_h / BARCODE_HEIGHT;
1660 int BW = 108 /*BARCODE_WIDTH*/;
1661 int BH = BARCODE_HEIGHT;
1663 b->mag = (mag_x < mag_y ? mag_x : mag_y);
1665 b->x = (x * cell_w) + ((cell_w - b->mag * BW) / 2);
1666 b->y = (y * cell_h) + ((cell_h - b->mag * BH) / 2);
1672 char *s = malloc (digits + 10);
1674 for (j = 0; j < digits; j++)
1675 s[j] = (random() % 10) + '0';
1681 /* change one digit in this barcode */
1682 strings[i][random() % digits] = (random() % 10) + '0';
1684 strcpy (b->code, strings[i]);
1685 processUpcEan (b->code, b->bitmap);
1691 /* render and display the current model */
1692 static void renderFrame (void)
1696 for (i = 0; i < barcode_count; i++)
1698 Barcode *barcode = &barcodes[i];
1700 if (barcode->x > windowWidth) {
1704 /* bitmapScale (theBitmap, barcode->bitmap, barcode->mag);*/
1705 theImage->data = barcode->bitmap->buf;
1707 XSetForeground (display, theGC, barcode->pixel);
1708 XPutImage (display, window, theGC, theImage,
1709 0, 0, barcode->x, barcode->y,
1710 BARCODE_WIDTH * barcode->mag,
1711 BARCODE_HEIGHT * barcode->mag);
1715 /* do one iteration */
1716 static void oneIteration (void)
1727 /* main and options and stuff */
1729 char *progclass = "Barcode";
1731 char *defaults [] = {
1732 ".background: black",
1733 ".foreground: white",
1738 XrmOptionDescRec options [] = {
1739 { "-delay", ".delay", XrmoptionSepArg, 0 },
1743 /* initialize the user-specifiable params */
1744 static void initParams (void)
1748 delay = get_integer_resource ("delay", "Delay");
1751 fprintf (stderr, "error: delay must be at least 0\n");
1764 void screenhack (Display *dpy, Window win)
1777 screenhack_handle_events (dpy);