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.
17 #include "screenhack.h"
19 /* non-user-modifiable immutable definitions */
23 /* random float in the range (0..1) */
24 #define RAND_FLOAT_01 \
25 (((FLOAT) ((random() >> 8) & 0xffff)) / ((FLOAT) 0x10000))
27 #define BARCODE_WIDTH (164)
28 #define BARCODE_HEIGHT (69)
32 /* simple bitmap structure */
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 */
62 /* parameters that are user configurable */
64 /* delay (usec) between iterations */
67 /* width and height of the window */
71 Visual *visual; /* the visual to use */
72 Colormap cmap; /* the colormap of the window */
74 GC theGC; /* GC for drawing */
75 unsigned long fg_pixel, grid_pixel;
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 */
84 XImage *theImage; /* ginormo image for drawing */
85 Bitmap *theBitmap; /* ginormo bitmap for drawing */
87 enum { BC_SCROLL, BC_GRID, BC_CLOCK12, BC_CLOCK24 } mode;
93 /* a bunch of words */
94 static const char *words[] =
368 #define WORD_COUNT (sizeof(words) / sizeof(char *))
372 /* ----------------------------------------------------------------------------
373 * bitmap manipulation
376 /* construct a new bitmap */
377 static Bitmap *makeBitmap (int width, int height)
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);
388 static void bitmapClear (Bitmap *b)
390 memset (b->buf, 0, b->widthBytes * b->height);
395 static void bitmapFree (Bitmap *b)
403 /* get the byte value at the given byte-offset coordinates in the given
405 static int bitmapGetByte (Bitmap *b, int xByte, int y)
408 (xByte >= b->widthBytes) ||
412 /* out-of-range get returns 0 */
416 return b->buf[b->widthBytes * y + xByte];
419 /* get the bit value at the given coordinates in the given bitmap */
420 static int bitmapGet (Bitmap *b, int x, int y)
424 int byteValue = bitmapGetByte (b, xbyte, y);
426 return (byteValue & (1 << xbit)) >> xbit;
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)
440 /* ignore out-of-range set */
446 b->buf[b->widthBytes * y + xbyte] |= 1 << xbit;
450 b->buf[b->widthBytes * y + xbyte] &= ~(1 << xbit);
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)
460 for (y = 0; y < height; y++)
462 for (x = 0; x < width; x++)
464 bitmapSet (dest, x + dx, y + dy, bitmapGet (src, x + sx, y + sy));
469 /* draw a vertical line in the given bitmap */
470 static void bitmapVlin (Bitmap *b, int x, int y1, int y2)
474 bitmapSet (b, x, y1, 1);
479 /* scale a bitmap into another bitmap */
480 static void bitmapScale (Bitmap *dest, Bitmap *src, int mag)
484 for (y = 0; y < BARCODE_HEIGHT; y++)
486 for (x = 0; x < BARCODE_WIDTH; x++)
488 int v = bitmapGet (src, x, y);
489 for (x2 = 0; x2 < mag; x2++)
491 for (y2 = 0; y2 < mag; y2++)
493 bitmapSet (dest, x * mag + x2, y * mag + y2, v);
501 /* ----------------------------------------------------------------------------
502 * character generation
505 static unsigned char font5x8Buf[] =
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
595 static Bitmap font5x8 = { 8, 1024, 1, (char *) font5x8Buf };
597 /* draw the given 5x8 character at the given coordinates */
598 static void bitmapDrawChar5x8 (Bitmap *b, int x, int y, char c)
600 bitmapCopyRect (b, x, y, &font5x8, 0, c * 8, 5, 8);
603 /* draw a string of 5x8 characters at the given coordinates */
604 static void bitmapDrawString5x8 (Bitmap *b, int x, int y, char *str)
623 bitmapDrawChar5x8 (b, x, y, c);
632 /* ----------------------------------------------------------------------------
633 * upc/ean symbologies
636 /* A quick lesson in UPC and EAN barcodes:
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
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
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.)
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:
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.
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.
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:
706 * First digit 0 First digit 1
707 * Explicit Digit Explicit Digit
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
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
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
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.
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
756 * Lower 2 bits Parity Pattern
757 * ------------ --------------
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.
771 /* enum to indicate which pattern set to use */
774 UPC_LEFT_A, UPC_LEFT_B, UPC_RIGHT
778 /* the Left A patterns */
779 static unsigned int upcLeftA[] = {
780 0x0d, 0x19, 0x13, 0x3d, 0x23, 0x31, 0x2f, 0x3b, 0x37, 0x0b
783 /* the Left B patterns */
784 static unsigned int upcLeftB[] = {
785 0x27, 0x33, 0x1b, 0x21, 0x1d, 0x39, 0x05, 0x11, 0x09, 0x17
788 /* the Right patterns */
789 static unsigned int upcRight[] = {
790 0x72, 0x66, 0x6c, 0x42, 0x5c, 0x4e, 0x50, 0x44, 0x48, 0x74
793 /* the EAN-13 first-digit patterns */
794 static unsigned int ean13FirstDigit[] = {
795 0x00, 0x0b, 0x0d, 0x0e, 0x13, 0x19, 0x1c, 0x15, 0x16, 0x1a
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
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)
808 if ((c >= '0') && (c <= '9'))
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)
822 if (st->mode != BC_CLOCK24 &&
823 st->mode != BC_CLOCK12)
824 if ((c < '0') || (c > '9'))
827 bitmapDrawChar5x8 (b, x, y, c);
830 /* draw a upc/ean digit at the given coordinates */
831 static void drawUpcEanDigit (Bitmap *upcBitmap, int x, int y1, int y2, char n,
841 bits = upcLeftA[(int) n];
844 bits = upcLeftB[(int) n];
846 default /* case UPC_RIGHT */:
847 bits = upcRight[(int) n];
851 for (i = 6; i >=0; i--)
855 bitmapVlin (upcBitmap, x, y1, y2);
861 /* report the width of the given supplemental code or 0 if it is a bad
863 static int upcEanSupplementWidth (char *digits)
865 switch (strlen (digits))
867 case 2: return 28; /* 8 + 4 + 2*7 + 1*2 */
868 case 5: return 55; /* 8 + 4 + 5*7 + 4*2 */
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)
878 int len = strlen (digits);
895 x += 8; /* skip the space between the main and supplemental */
902 parity = (charToDigit (digits[0]) * 10 +
903 charToDigit (digits[1])) & 0x3;
910 ((charToDigit (digits[0]) + charToDigit (digits[2]) +
911 charToDigit (digits[4])) * 3
912 + (charToDigit (digits[1]) + charToDigit (digits[3])) * 9)
914 parity = upcELastDigit[parity];
919 fprintf (stderr, "%s: bad supplement (%d digits)\n",
927 bitmapVlin (upcBitmap, x, y, y2);
928 bitmapVlin (upcBitmap, x + 2, y, y2);
929 bitmapVlin (upcBitmap, x + 3, y, y2);
931 for (i = 0; i < len; i++)
934 (parity & (1 << (len - 1 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
935 int baseX = x + 2 + i * 9;
937 /* separator / end of header */
940 bitmapVlin (upcBitmap, baseX, y, y2);
942 bitmapVlin (upcBitmap, baseX + 1, y, y2);
944 drawUpcEanDigit (upcBitmap,
951 drawDigitChar (st, upcBitmap, textX + i*6, textY, digits[i]);
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)
962 bitmapVlin (upcBitmap, x, y, guardY2);
963 bitmapVlin (upcBitmap, x + 2, y, guardY2);
966 bitmapVlin (upcBitmap, x + 46, y, guardY2);
967 bitmapVlin (upcBitmap, x + 48, y, guardY2);
970 bitmapVlin (upcBitmap, x + 92, y, guardY2);
971 bitmapVlin (upcBitmap, x + 94, y, guardY2);
973 for (i = 0; i < 6; i++)
975 drawUpcEanDigit (upcBitmap,
978 (i == 0) ? guardY2 : barY2,
981 drawUpcEanDigit (upcBitmap,
984 (i == 5) ? guardY2 : barY2,
990 /* make and return a full-height UPC-A barcode */
991 static int makeUpcAFull (struct state *st, Bitmap *dest, char *digits, int y)
996 int height = baseHeight + y;
1000 drawUpcABars (dest, digits, 6, y, height - 10, height - 4);
1002 drawDigitChar (st, dest, 0, height - 14, digits[0]);
1004 for (i = 0; i < 5; i++)
1006 drawDigitChar (st, dest, 18 + i*7, height - 7, digits[i+1]);
1007 drawDigitChar (st, dest, 57 + i*7, height - 7, digits[i+6]);
1010 drawDigitChar (st, dest, 103, height - 14, digits[11]);
1015 /* make and return a UPC-A barcode */
1016 static int makeUpcA (struct state *st, Bitmap *dest, char *digits, int y)
1019 unsigned int mul = 3;
1020 unsigned int sum = 0;
1022 for (i = 0; i < 11; i++)
1024 sum += charToDigit (digits[i]) * mul;
1028 if (digits[11] == '?')
1030 digits[11] = ((10 - (sum % 10)) % 10) + '0';
1033 return makeUpcAFull (st, dest, digits, y);
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)
1042 int parityPattern = upcELastDigit[charToDigit(digits[7])];
1044 int clockp = (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24);
1046 if (digits[0] == '1')
1048 parityPattern = ~parityPattern;
1052 bitmapVlin (upcBitmap, x, y, guardY2);
1053 bitmapVlin (upcBitmap, x + 2, y, guardY2);
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);
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.
1066 bitmapVlin (upcBitmap, x + 18, y, guardY2);
1067 bitmapVlin (upcBitmap, x + 18 + 2, y, guardY2);
1069 bitmapVlin (upcBitmap, x + 36, y, guardY2);
1070 bitmapVlin (upcBitmap, x + 36 + 2, y, guardY2);
1073 for (i = 0; i < 6; i++)
1076 (parityPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
1079 i < 4 ? 4 : /* extra spacing for clock bars */
1082 drawUpcEanDigit (upcBitmap,
1091 /* make and return a full-height UPC-E barcode */
1092 static int makeUpcEFull (struct state *st, Bitmap *dest, char *digits, int y)
1095 int baseHeight = 60;
1097 int height = baseHeight + y;
1101 drawUpcEBars (st, dest, digits, 6, y, height - 10, height - 4);
1103 drawDigitChar (st, dest, 0, height - 14, digits[0]);
1105 for (i = 0; i < 6; i++)
1107 drawDigitChar (st, dest, 11 + i*7, height - 7, digits[i+1]);
1110 drawDigitChar (st, dest, 59, height - 14, digits[7]);
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)
1123 if ((compressed[0] != '0') && (compressed[0] != '1'))
1128 expanded[0] = compressed[0];
1131 expanded[11] = compressed[7];
1133 switch (compressed[6])
1139 expanded[1] = compressed[1];
1140 expanded[2] = compressed[2];
1141 expanded[3] = compressed[6];
1144 expanded[8] = compressed[3];
1145 expanded[9] = compressed[4];
1146 expanded[10] = compressed[5];
1151 expanded[1] = compressed[1];
1152 expanded[2] = compressed[2];
1153 expanded[3] = compressed[3];
1157 expanded[9] = compressed[4];
1158 expanded[10] = compressed[5];
1163 expanded[1] = compressed[1];
1164 expanded[2] = compressed[2];
1165 expanded[3] = compressed[3];
1166 expanded[4] = compressed[4];
1170 expanded[10] = compressed[5];
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];
1182 expanded[10] = compressed[6];
1187 if (expanded[11] == '?')
1189 unsigned int mul = 3;
1190 unsigned int sum = 0;
1192 for (i = 0; i < 11; i++)
1194 sum += charToDigit (expanded[i]) * mul;
1198 expanded[11] = ((10 - (sum % 10)) % 10) + '0';
1202 /* make and return a UPC-E barcode */
1203 static int makeUpcE (struct state *st, Bitmap *dest, char *digits, int y)
1205 char expandedDigits[13];
1206 char compressedDigits[9];
1208 expandedDigits[0] = '\0';
1209 compressedDigits[0] = '0';
1210 strcpy (compressedDigits + 1, digits);
1212 expandToUpcADigits (compressedDigits, expandedDigits);
1213 if (expandedDigits[0] == '\0')
1218 compressedDigits[7] = expandedDigits[11];
1220 return makeUpcEFull (st, dest, compressedDigits, y);
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)
1228 int leftPattern = ean13FirstDigit[charToDigit (digits[0])];
1231 bitmapVlin (upcBitmap, x, y, guardY2);
1232 bitmapVlin (upcBitmap, x + 2, y, guardY2);
1235 bitmapVlin (upcBitmap, x + 46, y, guardY2);
1236 bitmapVlin (upcBitmap, x + 48, y, guardY2);
1239 bitmapVlin (upcBitmap, x + 92, y, guardY2);
1240 bitmapVlin (upcBitmap, x + 94, y, guardY2);
1242 for (i = 0; i < 6; i++)
1244 UpcSet lset = (leftPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
1246 drawUpcEanDigit (upcBitmap,
1252 drawUpcEanDigit (upcBitmap,
1261 /* make and return a full-height EAN-13 barcode */
1262 static int makeEan13Full (struct state *st, Bitmap *dest, char *digits, int y)
1264 int baseWidth = 102;
1265 int baseHeight = 60;
1267 int height = baseHeight + y;
1271 drawEan13Bars (dest, digits, 6, y, height - 10, height - 4);
1273 drawDigitChar (st, dest, 0, height - 7, digits[0]);
1275 for (i = 0; i < 6; i++)
1277 drawDigitChar (st, dest, 11 + i*7, height - 7, digits[i+1]);
1278 drawDigitChar (st, dest, 57 + i*7, height - 7, digits[i+7]);
1284 /* make and return an EAN-13 barcode */
1285 static int makeEan13 (struct state *st, Bitmap *dest, char *digits, int y)
1288 unsigned int mul = 1;
1289 unsigned int sum = 0;
1291 for (i = 0; i < 12; i++)
1293 sum += charToDigit (digits[i]) * mul;
1297 if (digits[12] == '?')
1299 digits[12] = ((10 - (sum % 10)) % 10) + '0';
1302 return makeEan13Full (st, dest, digits, y);
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)
1312 bitmapVlin (upcBitmap, x, y, guardY2);
1313 bitmapVlin (upcBitmap, x + 2, y, guardY2);
1316 bitmapVlin (upcBitmap, x + 32, y, guardY2);
1317 bitmapVlin (upcBitmap, x + 34, y, guardY2);
1320 bitmapVlin (upcBitmap, x + 64, y, guardY2);
1321 bitmapVlin (upcBitmap, x + 66, y, guardY2);
1323 for (i = 0; i < 4; i++)
1325 drawUpcEanDigit (upcBitmap,
1331 drawUpcEanDigit (upcBitmap,
1340 /* make and return a full-height EAN-8 barcode */
1341 static int makeEan8Full (struct state *st, Bitmap *dest, char *digits, int y)
1344 int baseHeight = 60;
1346 int height = baseHeight + y;
1350 drawEan8Bars (dest, digits, 0, y, height - 10, height - 4);
1352 for (i = 0; i < 4; i++)
1354 drawDigitChar (st, dest, 5 + i*7, height - 7, digits[i]);
1355 drawDigitChar (st, dest, 37 + i*7, height - 7, digits[i+4]);
1361 /* make and return an EAN-8 barcode */
1362 static int makeEan8 (struct state *st, Bitmap *dest, char *digits, int y)
1365 unsigned int mul = 3;
1366 unsigned int sum = 0;
1368 for (i = 0; i < 7; i++)
1370 sum += charToDigit (digits[i]) * mul;
1374 if (digits[7] == '?')
1376 digits[7] = ((10 - (sum % 10)) % 10) + '0';
1379 return makeEan8Full (st, dest, digits, y);
1382 /* Dispatch to the right form factor UPC/EAN barcode generator */
1383 static void processUpcEan (struct state *st, char *str, Bitmap *dest)
1388 int supDigitCount = 0;
1390 char *banner = NULL;
1395 while ((digitCount < 15) && (supDigitCount < 7))
1398 if (((c >= '0') && (c <= '9')) || (c == '?'))
1402 supDigits[supDigitCount] = *instr;
1407 digits[digitCount] = *instr;
1427 digits[digitCount] = '\0';
1428 supDigits[supDigitCount] = '\0';
1430 if (supDigitCount == 0)
1434 else if ((supDigitCount == 2) || (supDigitCount == 5))
1436 supplement = upcEanSupplementWidth (supDigits);
1440 fprintf (stderr, "%s: invalid supplement (must be 2 or 5 digits)\n",
1454 width = makeUpcE (st, dest, digits, vstart);
1459 width = makeEan8 (st, dest, digits, vstart);
1464 width = makeUpcA (st, dest, digits, vstart);
1469 width = makeEan13 (st, dest, digits, vstart);
1474 fprintf (stderr, "%s: bad barcode (%d digits)\n",
1475 progname, digitCount);
1482 drawUpcEanSupplementalBars (st, dest, supDigits,
1484 vstart + 1, dest->height - 4, 1);
1489 bitmapDrawString5x8 (dest,
1490 (width + supplement -
1491 ((int) strlen (banner) * 5)) / 2,
1499 /* ----------------------------------------------------------------------------
1504 * overall setup stuff
1507 /* set up the system */
1508 static void setup (struct state *st)
1510 XWindowAttributes xgwa;
1513 XGetWindowAttributes (st->dpy, st->window, &xgwa);
1515 st->visual = xgwa.visual;
1516 st->cmap = xgwa.colormap;
1517 st->windowWidth = xgwa.width;
1518 st->windowHeight = xgwa.height;
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);
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;
1541 /* set up the model */
1542 static void setupModel (struct state *st)
1546 st->barcode_max = 20;
1547 st->barcode_count = 0;
1548 st->barcodes = malloc (sizeof (Barcode) * st->barcode_max);
1550 for (i = 0; i < st->barcode_max; i++)
1552 st->barcodes[i].bitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG,
1553 BARCODE_HEIGHT * MAX_MAG);
1557 /* make a new barcode string */
1558 static void makeBarcodeString (struct state *st, char *str)
1562 switch ((int) (RAND_FLOAT_01 * 4))
1564 case 0: dig = 6; break;
1565 case 1: dig = 7; break;
1566 case 2: dig = 11; break;
1567 default: dig = 12; break;
1570 for (i = 0; i < dig; i++)
1572 str[i] = RAND_FLOAT_01 * 10 + '0';
1578 switch ((int) (RAND_FLOAT_01 * 3))
1580 case 0: dig = 0; break;
1581 case 1: dig = 2; break;
1582 default: dig = 5; break;
1591 str[i] = RAND_FLOAT_01 * 10 + '0';
1600 strcpy(&str[i], words[(int) (RAND_FLOAT_01 * WORD_COUNT)]);
1603 /* update the model for one iteration */
1604 static void scrollModel (struct state *st)
1608 for (i = 0; i < st->barcode_count; i++)
1610 Barcode *b = &st->barcodes[i];
1612 if ((b->x + BARCODE_WIDTH * b->mag) < 0)
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;
1620 XFreeColors (st->dpy, st->cmap, &b->pixel, 1, 0);
1624 st->barcode_count--;
1628 while (st->barcode_count < st->barcode_max)
1630 Barcode *barcode = &st->barcodes[st->barcode_count];
1631 barcode->x = (st->barcode_count == 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;
1638 RAND_FLOAT_01 * (st->windowHeight - BARCODE_HEIGHT * barcode->mag);
1643 makeBarcodeString(st, barcode->code);
1644 processUpcEan (st, barcode->code, st->theBitmap);
1645 bitmapScale (barcode->bitmap, st->theBitmap, barcode->mag);
1650 for (ii = 0; ii < 100; ii++)
1652 hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1653 ok = XAllocColor (st->dpy, st->cmap, &c);
1658 c.red = c.green = c.blue = 0xFFFF;
1659 if (!XAllocColor (st->dpy, st->cmap, &c))
1662 barcode->pixel = c.pixel;
1665 st->barcode_count++;
1669 /* update the model for one iteration */
1670 static void updateGrid (struct state *st)
1674 if (st->grid_w == 0 || st->grid_h == 0 ||
1675 (! (random() % 400)))
1677 XClearWindow (st->dpy, st->window);
1678 st->grid_w = 1 + (random() % 3);
1679 st->grid_h = 1 + (random() % 4);
1682 if (!st->grid_alloced_p || (! (random() % 100)))
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;
1693 st->barcode_count = st->grid_w * st->grid_h;
1694 if (st->barcode_count > st->barcode_max) abort();
1696 for (i = 0; i < st->barcode_max; i++)
1698 Barcode *b = &st->barcodes[i];
1699 b->x = b->y = 999999;
1703 for (y = 0; y < st->grid_h; y++)
1704 for (x = 0; x < st->grid_w; x++, i++)
1706 Barcode *b = &st->barcodes[i];
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;
1716 b->mag = (mag_x < mag_y ? mag_x : mag_y);
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;
1722 if (!st->strings[i])
1725 char *s = malloc (digits + 10);
1727 for (j = 0; j < digits; j++)
1728 s[j] = (random() % 10) + '0';
1734 /* change one digit in this barcode */
1735 st->strings[i][random() % digits] = (random() % 10) + '0';
1737 strcpy (b->code, st->strings[i]);
1738 processUpcEan (st, b->code, b->bitmap);
1743 /* update the model for one iteration.
1744 This one draws a clock. By jwz. */
1745 static void updateClock (struct state *st)
1747 Barcode *b = &st->barcodes[0];
1748 int BW = 76 /* BARCODE_WIDTH */;
1749 int BH = BARCODE_HEIGHT;
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;
1758 XGetWindowAttributes (st->dpy, st->window, &xgwa);
1759 st->windowWidth = xgwa.width;
1760 st->windowHeight = xgwa.height;
1762 mag_x = st->windowWidth / BW;
1763 mag_y = st->windowHeight / BH;
1765 st->barcode_count = 1;
1767 b->mag = (mag_x < mag_y ? mag_x : mag_y);
1769 if (b->mag > MAX_MAG) b->mag = MAX_MAG;
1770 if (b->mag < 1) b->mag = 1;
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;
1776 if (!st->button_down_p)
1777 sprintf (b->code, "0%02d%02d%02d?:",
1778 (st->mode == BC_CLOCK24
1788 sprintf (b->code, "0%02d%02d%02d?:",
1789 tm->tm_year % 100, tm->tm_mon+1, tm->tm_mday);
1793 int hh = BH + vstart;
1794 char expandedDigits[13];
1796 expandedDigits[0] = '\0';
1798 expandToUpcADigits (b->code, expandedDigits);
1799 if (expandedDigits[0] != '\0')
1800 b->code[7] = expandedDigits[11];
1802 bitmapClear (st->theBitmap);
1803 drawUpcEBars (st, st->theBitmap, b->code, 6, 9, 59, 65);
1804 for (i = 0; i < 6; i++)
1806 int off = (i < 2 ? 0 :
1809 drawDigitChar (st, st->theBitmap, 11 + i*7 + off, hh - 16, b->code[i+1]);
1812 if (!st->button_down_p)
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);
1819 drawDigitChar (st, st->theBitmap, 0, hh - 23, (tm->tm_hour < 12 ? 'A' : 'P'));
1820 drawDigitChar (st, st->theBitmap, 68, hh - 23, 'M');
1825 sprintf (s, "%03d", tm->tm_yday);
1826 bitmapDrawString5x8 (st->theBitmap, (BW - strlen (s)*5) / 2, 0, s);
1830 bitmapScale (b->bitmap, st->theBitmap, b->mag);
1832 if (ow != st->windowWidth || oh != st->windowHeight)
1833 XClearWindow (st->dpy, st->window);
1838 /* render and dpy the current model */
1839 static void renderFrame (struct state *st)
1843 for (i = 0; i < st->barcode_count; i++)
1845 Barcode *barcode = &st->barcodes[i];
1847 if (barcode->x > st->windowWidth) {
1851 /* bitmapScale (st->theBitmap, barcode->bitmap, barcode->mag);*/
1852 st->theImage->data = barcode->bitmap->buf;
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);
1862 /* do one iteration */
1863 static unsigned long
1864 barcode_draw (Display *dpy, Window win, void *closure)
1866 struct state *st = (struct state *) closure;
1867 if (st->mode == BC_SCROLL)
1869 else if (st->mode == BC_GRID)
1871 else if (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24)
1883 barcode_event (Display *dpy, Window window, void *closure, XEvent *event)
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;
1890 } else if (clockp && event->xany.type == ButtonRelease) {
1891 st->button_down_p = False;
1898 barcode_reshape (Display *dpy, Window window, void *closure,
1899 unsigned int w, unsigned int h)
1904 barcode_free (Display *dpy, Window window, void *closure)
1909 /* main and options and stuff */
1911 static const char *barcode_defaults [] = {
1912 ".background: black",
1913 ".foreground: green",
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" },
1931 /* initialize the user-specifiable params */
1932 static void initParams (struct state *st)
1937 st->delay = get_integer_resource (st->dpy, "delay", "Delay");
1940 fprintf (stderr, "%s: delay must be at least 0\n", progname);
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"))
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;
1956 fprintf (stderr, "%s: unknown mode \"%s\"\n", progname, s);
1961 if (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24)
1962 st->delay = 10000; /* only update every 1/10th second */
1971 barcode_init (Display *dpy, Window win)
1973 struct state *st = (struct state *) calloc (1, sizeof(*st));
1984 XSCREENSAVER_MODULE ("Barcode", barcode)