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.
18 #include "screenhack.h"
20 /* non-user-modifiable immutable definitions */
24 /* random float in the range (0..1) */
25 #define RAND_FLOAT_01 \
26 (((FLOAT) ((random() >> 8) & 0xffff)) / ((FLOAT) 0x10000))
28 #define BARCODE_WIDTH (164)
29 #define BARCODE_HEIGHT (69)
33 /* simple bitmap structure */
50 int x; /* x coordinate of the left of the barcode */
51 int y; /* y coordinate of the left of the barcode */
52 int mag; /* magnfication factor */
53 Bitmap *bitmap; /* the bitmap */
54 char code[128]; /* the barcode string */
55 unsigned long pixel; /* the color */
63 /* parameters that are user configurable */
65 /* delay (usec) between iterations */
68 /* width and height of the window */
72 Visual *visual; /* the visual to use */
73 Colormap cmap; /* the colormap of the window */
75 GC theGC; /* GC for drawing */
76 unsigned long fg_pixel, grid_pixel;
81 Barcode *barcodes; /* array of barcodes */
82 int barcode_count; /* how many barcodes are currently active */
83 int barcode_max; /* the maximum number of active barcodes */
85 XImage *theImage; /* ginormo image for drawing */
86 Bitmap *theBitmap; /* ginormo bitmap for drawing */
88 enum { BC_SCROLL, BC_GRID, BC_CLOCK12, BC_CLOCK24 } mode;
94 /* a bunch of words */
95 static const char *words[] =
369 #define WORD_COUNT (sizeof(words) / sizeof(char *))
373 /* ----------------------------------------------------------------------------
374 * bitmap manipulation
377 /* construct a new bitmap */
378 static Bitmap *makeBitmap (int width, int height)
380 Bitmap *result = malloc (sizeof (Bitmap));
381 result->width = width;
382 result->height = height;
383 result->widthBytes = (width + 7) / 8;
384 result->buf = calloc (1, height * result->widthBytes);
389 static void bitmapClear (Bitmap *b)
391 memset (b->buf, 0, b->widthBytes * b->height);
396 static void bitmapFree (Bitmap *b)
404 /* get the byte value at the given byte-offset coordinates in the given
406 static int bitmapGetByte (Bitmap *b, int xByte, int y)
409 (xByte >= b->widthBytes) ||
413 /* out-of-range get returns 0 */
417 return b->buf[b->widthBytes * y + xByte];
420 /* get the bit value at the given coordinates in the given bitmap */
421 static int bitmapGet (Bitmap *b, int x, int y)
425 int byteValue = bitmapGetByte (b, xbyte, y);
427 return (byteValue & (1 << xbit)) >> xbit;
430 /* set the bit value at the given coordinates in the given bitmap */
431 static void bitmapSet (Bitmap *b, int x, int y, int value)
441 /* ignore out-of-range set */
447 b->buf[b->widthBytes * y + xbyte] |= 1 << xbit;
451 b->buf[b->widthBytes * y + xbyte] &= ~(1 << xbit);
455 /* copy the given rectangle to the given destination from the given source. */
456 static void bitmapCopyRect (Bitmap *dest, int dx, int dy,
457 Bitmap *src, int sx, int sy, int width, int height)
461 for (y = 0; y < height; y++)
463 for (x = 0; x < width; x++)
465 bitmapSet (dest, x + dx, y + dy, bitmapGet (src, x + sx, y + sy));
470 /* draw a vertical line in the given bitmap */
471 static void bitmapVlin (Bitmap *b, int x, int y1, int y2)
475 bitmapSet (b, x, y1, 1);
480 /* scale a bitmap into another bitmap */
481 static void bitmapScale (Bitmap *dest, Bitmap *src, int mag)
485 for (y = 0; y < BARCODE_HEIGHT; y++)
487 for (x = 0; x < BARCODE_WIDTH; x++)
489 int v = bitmapGet (src, x, y);
490 for (x2 = 0; x2 < mag; x2++)
492 for (y2 = 0; y2 < mag; y2++)
494 bitmapSet (dest, x * mag + x2, y * mag + y2, v);
502 /* ----------------------------------------------------------------------------
503 * character generation
506 static unsigned char font5x8Buf[] =
508 0x1e, 0x01, 0x06, 0x01, 0x1e, 0x00, 0x1e, 0x01, 0x06, 0x01, 0x1e, 0x00,
509 0x1e, 0x01, 0x1e, 0x01, 0x1e, 0x00, 0x01, 0x00, 0x1f, 0x08, 0x04, 0x08,
510 0x1f, 0x00, 0x11, 0x1f, 0x11, 0x00, 0x1f, 0x01, 0x01, 0x00, 0x1f, 0x04,
511 0x0a, 0x11, 0x00, 0x01, 0x00, 0x0e, 0x11, 0x11, 0x00, 0x0e, 0x11, 0x11,
512 0x0e, 0x00, 0x1f, 0x08, 0x04, 0x08, 0x1f, 0x00, 0x44, 0x41, 0x4e, 0x20,
513 0x42, 0x4f, 0x52, 0x4e, 0x53, 0x54, 0x45, 0x49, 0x4e, 0x21, 0x21, 0x00,
514 0x66, 0x6e, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
515 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
516 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
517 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
518 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
519 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
520 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
521 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
522 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
523 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
524 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
525 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
526 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
527 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
528 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
529 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x05, 0x05, 0x00,
531 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x00,
532 0x02, 0x0f, 0x01, 0x0f, 0x08, 0x0f, 0x04, 0x00, 0x0b, 0x0b, 0x08, 0x06,
533 0x01, 0x0d, 0x0d, 0x00, 0x03, 0x05, 0x02, 0x05, 0x0d, 0x05, 0x0b, 0x00,
534 0x04, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x02,
535 0x02, 0x02, 0x04, 0x00, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x00,
536 0x00, 0x09, 0x06, 0x0f, 0x06, 0x09, 0x00, 0x00, 0x00, 0x02, 0x02, 0x07,
537 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x06, 0x00,
538 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x04, 0x06, 0x02, 0x01, 0x01, 0x00,
540 0x0f, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x06, 0x04, 0x04, 0x04,
541 0x04, 0x04, 0x0f, 0x00, 0x0f, 0x09, 0x08, 0x0f, 0x01, 0x09, 0x0f, 0x00,
542 0x0f, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x0f, 0x00, 0x09, 0x09, 0x09, 0x0f,
543 0x08, 0x08, 0x08, 0x00, 0x0f, 0x09, 0x01, 0x0f, 0x08, 0x09, 0x0f, 0x00,
544 0x03, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0c,
545 0x04, 0x04, 0x04, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x0f, 0x00,
546 0x0f, 0x09, 0x09, 0x0f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00,
547 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x04, 0x06, 0x00,
548 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x0f, 0x00,
549 0x0f, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x04, 0x02, 0x01, 0x00,
550 0x0f, 0x09, 0x08, 0x0e, 0x02, 0x00, 0x02, 0x00, 0x0f, 0x09, 0x0d, 0x0d,
551 0x0d, 0x01, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x09, 0x00,
552 0x07, 0x09, 0x09, 0x07, 0x09, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x01, 0x01,
553 0x01, 0x01, 0x0f, 0x00, 0x07, 0x09, 0x09, 0x09, 0x09, 0x09, 0x07, 0x00,
554 0x0f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x0f, 0x00, 0x0f, 0x01, 0x01, 0x0f,
555 0x01, 0x01, 0x01, 0x00, 0x0f, 0x01, 0x01, 0x0d, 0x09, 0x09, 0x0f, 0x00,
556 0x09, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x09, 0x00, 0x07, 0x02, 0x02, 0x02,
557 0x02, 0x02, 0x07, 0x00, 0x0e, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x00,
558 0x09, 0x09, 0x09, 0x07, 0x09, 0x09, 0x09, 0x00, 0x01, 0x01, 0x01, 0x01,
559 0x01, 0x01, 0x0f, 0x00, 0x09, 0x0f, 0x0f, 0x0f, 0x09, 0x09, 0x09, 0x00,
560 0x09, 0x0b, 0x0d, 0x09, 0x09, 0x09, 0x09, 0x00, 0x0f, 0x09, 0x09, 0x09,
561 0x09, 0x09, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x01, 0x01, 0x01, 0x00,
562 0x0f, 0x09, 0x09, 0x09, 0x0b, 0x05, 0x0b, 0x00, 0x07, 0x09, 0x09, 0x07,
563 0x09, 0x09, 0x09, 0x00, 0x0f, 0x01, 0x01, 0x0f, 0x08, 0x08, 0x0f, 0x00,
564 0x0f, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x09, 0x09, 0x09, 0x09,
565 0x09, 0x09, 0x0f, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x05, 0x02, 0x00,
566 0x09, 0x09, 0x09, 0x09, 0x0f, 0x0f, 0x09, 0x00, 0x09, 0x09, 0x05, 0x06,
567 0x0a, 0x09, 0x09, 0x00, 0x09, 0x09, 0x09, 0x0f, 0x08, 0x08, 0x0f, 0x00,
568 0x0f, 0x08, 0x08, 0x06, 0x01, 0x01, 0x0f, 0x00, 0x0e, 0x02, 0x02, 0x02,
569 0x02, 0x02, 0x0e, 0x00, 0x01, 0x01, 0x02, 0x06, 0x04, 0x08, 0x08, 0x00,
570 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x00, 0x02, 0x05, 0x05, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
572 0x02, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08,
573 0x0f, 0x09, 0x0f, 0x00, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x09, 0x0f, 0x00,
574 0x00, 0x00, 0x0f, 0x01, 0x01, 0x01, 0x0f, 0x00, 0x08, 0x08, 0x0f, 0x09,
575 0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x09, 0x0f, 0x01, 0x0f, 0x00,
576 0x0e, 0x02, 0x0f, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x09,
577 0x09, 0x0f, 0x08, 0x0c, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x09, 0x09, 0x00,
578 0x02, 0x00, 0x03, 0x02, 0x02, 0x02, 0x07, 0x00, 0x04, 0x00, 0x04, 0x04,
579 0x04, 0x04, 0x05, 0x07, 0x01, 0x01, 0x09, 0x05, 0x03, 0x05, 0x09, 0x00,
580 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x00, 0x00, 0x09, 0x0f,
581 0x0f, 0x09, 0x09, 0x00, 0x00, 0x00, 0x0f, 0x09, 0x09, 0x09, 0x09, 0x00,
582 0x00, 0x00, 0x0f, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x09,
583 0x09, 0x0f, 0x01, 0x01, 0x00, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x08, 0x08,
584 0x00, 0x00, 0x0f, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x01,
585 0x0f, 0x08, 0x0f, 0x00, 0x00, 0x02, 0x0f, 0x02, 0x02, 0x02, 0x0e, 0x00,
586 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x09, 0x09,
587 0x09, 0x05, 0x02, 0x00, 0x00, 0x00, 0x09, 0x09, 0x0f, 0x0f, 0x09, 0x00,
588 0x00, 0x00, 0x09, 0x09, 0x06, 0x09, 0x09, 0x00, 0x00, 0x00, 0x09, 0x09,
589 0x09, 0x0f, 0x08, 0x0c, 0x00, 0x00, 0x0f, 0x08, 0x06, 0x01, 0x0f, 0x00,
590 0x08, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08, 0x00, 0x02, 0x02, 0x02, 0x02,
591 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x04, 0x02, 0x02, 0x01, 0x00,
592 0x00, 0x0a, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
593 0x0f, 0x0f, 0x0f, 0x00
596 static Bitmap font5x8 = { 8, 1024, 1, (char *) font5x8Buf };
598 /* draw the given 5x8 character at the given coordinates */
599 static void bitmapDrawChar5x8 (Bitmap *b, int x, int y, char c)
601 bitmapCopyRect (b, x, y, &font5x8, 0, c * 8, 5, 8);
604 /* draw a string of 5x8 characters at the given coordinates */
605 static void bitmapDrawString5x8 (Bitmap *b, int x, int y, char *str)
624 bitmapDrawChar5x8 (b, x, y, c);
633 /* ----------------------------------------------------------------------------
634 * upc/ean symbologies
637 /* A quick lesson in UPC and EAN barcodes:
639 * Each digit consists of 2 bars and 2 spaces, taking a total width of 7
640 * times the width of the thinnest possible bar or space. There are three
641 * different possible representations for each digit, used depending on
642 * what side of a two-sided barcode the digit is used on, and to encode
643 * checksum or other information in some cases. The three forms are
644 * related. Taking as the "base" form the pattern as seen on the right-hand
645 * side of a UPC-A barcode, the other forms are the inverse of the base
646 * (that is, bar becomes space and vice versa) and the mirror image of the
647 * base. Still confused? Here's a complete table, where 0 means space and 1
650 * Left-A Left-B Right
651 * ------- ------- -------
652 * 0 0001101 0100111 1110010
653 * 1 0011001 0110011 1100110
654 * 2 0010011 0011011 1101100
655 * 3 0111101 0100001 1000010
656 * 4 0100011 0011101 1011100
657 * 5 0110001 0111001 1001110
658 * 6 0101111 0000101 1010000
659 * 7 0111011 0010001 1000100
660 * 8 0110111 0001001 1001000
661 * 9 0001011 0010111 1110100
663 * A UPC-A barcode consists of 6 patterns from Left-A on the left-hand side,
664 * 6 patterns from Right on the right-hand side, a guard pattern of 01010
665 * in the middle, and a guard pattern of 101 on each end. The 12th digit
666 * checksum is calculated as follows: Take the 1st, 3rd, ... 11th digits,
667 * sum them and multiplying by 3, and add that to the sum of the other digits.
668 * Subtract the final digit from 10, and that is the checksum digit. (If
669 * the last digit of the sum is 0, then the check digit is 0.)
671 * An EAN-13 barcode is just like a UPC-A barcode, except that the characters
672 * on the left-hand side have a pattern of Left-A and Left-B that encodes
673 * an extra first digit. Note that an EAN-13 barcode with the first digit
674 * of 0 is exactly the same as the UPC-A barcode of the rightmost 12 digits.
675 * The patterns to encode the first digit are as follows:
692 * The checksum for EAN-13 is just like UPC-A, except the 2nd, 4th, ... 12th
693 * digits are multiplied by 3 instead of the other way around.
695 * An EAN-8 barcode is just like a UPC-A barcode, except there are only 4
696 * digits in each half. Unlike EAN-13, there's no nonsense about different
697 * left-hand side patterns, either.
699 * A UPC-E barcode contains 6 explicit characters between a guard of 101
700 * on the left and 010101 on the right. The explicit characters are the
701 * middle six characters of the code. The first and last characters are
702 * encoded in the parity pattern of the six characters. There are two
703 * sets of parity patterns, one to use if the first digit of the number
704 * is 0, and another if it is 1. (UPC-E barcodes may only start with a 0
705 * or 1.) The patterns are as follows:
707 * First digit 0 First digit 1
708 * Explicit Digit Explicit Digit
710 * 1 2 3 4 5 6 1 2 3 4 5 6
711 * - - - - - - - - - - - -
712 * 0 b b b a a a a a a b b b
713 * 1 b b a b a a a a b a b b
714 * 2 b b a a b a a a b b a b
715 * 3 b b a a a b a a b b b a
716 * 4 b a b b a a a b a a b b
717 * 5 b a a b b a a b b a a b
718 * 6 b a a a b b a b b b a a
719 * 7 b a b a b a a b a b a b
720 * 8 b a b a a b a b a b b a
721 * 9 b a a b a b a b b a b a
723 * (Note that the two sets are the complements of each other. Also note
724 * that the first digit 1 patterns are mostly the same as the EAN-13
725 * first digit patterns.) The UPC-E check digit (the final digit encoded in
726 * the parity pattern) is the same as the UPC-A check digit for the
727 * expanded form of the UPC-E number. The expanstion is as follows, based
728 * on the last explicit digit (the second to last digit) in the encoded
732 * UPC-E form UPC-A form
733 * ---------- -------------
734 * XABCDE0Y XAB00000CDEY
735 * XABCDE1Y XAB10000CDEY
736 * XABCDE2Y XAB20000CDEY
737 * XABCDE3Y XABC00000DEY
738 * XABCDE4Y XABCD00000EY
739 * XABCDE5Y XABCDE00005Y
740 * XABCDE6Y XABCDE00006Y
741 * XABCDE7Y XABCDE00007Y
742 * XABCDE8Y XABCDE00008Y
743 * XABCDE9Y XABCDE00009Y
745 * All UPC/EAN barcodes may have an additional 2- or 5-digit supplemental
746 * code just to the right of the main barcode. The supplement starts about
747 * one digit-length (that is about 7 times the width of the thinnest bar)
748 * to the right of the main code, beginning with the guard pattern 1011.
749 * After that comes each digit, with a guard pattern of 01 between each,
750 * but not at the end. The digits are encoded using the left A and B
751 * characters to encode a parity pattern.
753 * For 2-digit supplements, the parity pattern is determined by the
754 * lower two bits of the numeric value of the code (e.g., 42 would use
757 * Lower 2 bits Parity Pattern
758 * ------------ --------------
764 * For 5-digit supplements, the parity pattern is calculated in a similar
765 * manner to check digit calculation: The first, third, and fifth digits
766 * are summed and multiplied by 3; the second and fourth digits are summed
767 * and multiplied by nine; the parity digit is the sum of those two numbers,
768 * modulo 10. The parity pattern is then the last five patterns from the
769 * UPC-E final digit 0 table for the corresponding digit.
772 /* enum to indicate which pattern set to use */
775 UPC_LEFT_A, UPC_LEFT_B, UPC_RIGHT
779 /* the Left A patterns */
780 static unsigned int upcLeftA[] = {
781 0x0d, 0x19, 0x13, 0x3d, 0x23, 0x31, 0x2f, 0x3b, 0x37, 0x0b
784 /* the Left B patterns */
785 static unsigned int upcLeftB[] = {
786 0x27, 0x33, 0x1b, 0x21, 0x1d, 0x39, 0x05, 0x11, 0x09, 0x17
789 /* the Right patterns */
790 static unsigned int upcRight[] = {
791 0x72, 0x66, 0x6c, 0x42, 0x5c, 0x4e, 0x50, 0x44, 0x48, 0x74
794 /* the EAN-13 first-digit patterns */
795 static unsigned int ean13FirstDigit[] = {
796 0x00, 0x0b, 0x0d, 0x0e, 0x13, 0x19, 0x1c, 0x15, 0x16, 0x1a
799 /* the UPC-E last-digit patterns for first digit 0 (complement for
800 * digit 1); also used for 5-digit supplemental check patterns */
801 static unsigned int upcELastDigit[] = {
802 0x38, 0x34, 0x32, 0x31, 0x2c, 0x26, 0x23, 0x2a, 0x29, 0x25
805 /* turn a character into an int representing its digit value; return
806 * 0 for things not in the range '0'-'9' */
807 static int charToDigit (char c)
809 if ((c >= '0') && (c <= '9'))
819 /* draw the given digit character at the given coordinates; a '0' is
820 * used in place of any non-digit character */
821 static void drawDigitChar (struct state *st, Bitmap *b, int x, int y, char c)
823 if (st->mode != BC_CLOCK24 &&
824 st->mode != BC_CLOCK12)
825 if ((c < '0') || (c > '9'))
828 bitmapDrawChar5x8 (b, x, y, c);
831 /* draw a upc/ean digit at the given coordinates */
832 static void drawUpcEanDigit (Bitmap *upcBitmap, int x, int y1, int y2, char n,
842 bits = upcLeftA[(int) n];
845 bits = upcLeftB[(int) n];
847 default /* case UPC_RIGHT */:
848 bits = upcRight[(int) n];
852 for (i = 6; i >=0; i--)
856 bitmapVlin (upcBitmap, x, y1, y2);
862 /* report the width of the given supplemental code or 0 if it is a bad
864 static int upcEanSupplementWidth (char *digits)
866 switch (strlen (digits))
868 case 2: return 28; /* 8 + 4 + 2*7 + 1*2 */
869 case 5: return 55; /* 8 + 4 + 5*7 + 4*2 */
874 /* draw the given supplemental barcode, including the textual digits */
875 static void drawUpcEanSupplementalBars (struct state *st,
876 Bitmap *upcBitmap, char *digits,
877 int x, int y, int y2, int textAbove)
879 int len = strlen (digits);
896 x += 8; /* skip the space between the main and supplemental */
903 parity = (charToDigit (digits[0]) * 10 +
904 charToDigit (digits[1])) & 0x3;
911 ((charToDigit (digits[0]) + charToDigit (digits[2]) +
912 charToDigit (digits[4])) * 3
913 + (charToDigit (digits[1]) + charToDigit (digits[3])) * 9)
915 parity = upcELastDigit[parity];
920 fprintf (stderr, "%s: bad supplement (%d digits)\n",
928 bitmapVlin (upcBitmap, x, y, y2);
929 bitmapVlin (upcBitmap, x + 2, y, y2);
930 bitmapVlin (upcBitmap, x + 3, y, y2);
932 for (i = 0; i < len; i++)
935 (parity & (1 << (len - 1 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
936 int baseX = x + 2 + i * 9;
938 /* separator / end of header */
941 bitmapVlin (upcBitmap, baseX, y, y2);
943 bitmapVlin (upcBitmap, baseX + 1, y, y2);
945 drawUpcEanDigit (upcBitmap,
952 drawDigitChar (st, upcBitmap, textX + i*6, textY, digits[i]);
956 /* draw the actual barcode part of a UPC-A barcode */
957 static void drawUpcABars (Bitmap *upcBitmap, char *digits, int x, int y,
958 int barY2, int guardY2)
963 bitmapVlin (upcBitmap, x, y, guardY2);
964 bitmapVlin (upcBitmap, x + 2, y, guardY2);
967 bitmapVlin (upcBitmap, x + 46, y, guardY2);
968 bitmapVlin (upcBitmap, x + 48, y, guardY2);
971 bitmapVlin (upcBitmap, x + 92, y, guardY2);
972 bitmapVlin (upcBitmap, x + 94, y, guardY2);
974 for (i = 0; i < 6; i++)
976 drawUpcEanDigit (upcBitmap,
979 (i == 0) ? guardY2 : barY2,
982 drawUpcEanDigit (upcBitmap,
985 (i == 5) ? guardY2 : barY2,
991 /* make and return a full-height UPC-A barcode */
992 static int makeUpcAFull (struct state *st, Bitmap *dest, char *digits, int y)
997 int height = baseHeight + y;
1001 drawUpcABars (dest, digits, 6, y, height - 10, height - 4);
1003 drawDigitChar (st, dest, 0, height - 14, digits[0]);
1005 for (i = 0; i < 5; i++)
1007 drawDigitChar (st, dest, 18 + i*7, height - 7, digits[i+1]);
1008 drawDigitChar (st, dest, 57 + i*7, height - 7, digits[i+6]);
1011 drawDigitChar (st, dest, 103, height - 14, digits[11]);
1016 /* make and return a UPC-A barcode */
1017 static int makeUpcA (struct state *st, Bitmap *dest, char *digits, int y)
1020 unsigned int mul = 3;
1021 unsigned int sum = 0;
1023 for (i = 0; i < 11; i++)
1025 sum += charToDigit (digits[i]) * mul;
1029 if (digits[11] == '?')
1031 digits[11] = ((10 - (sum % 10)) % 10) + '0';
1034 return makeUpcAFull (st, dest, digits, y);
1037 /* draw the actual barcode part of a UPC-E barcode */
1038 static void drawUpcEBars (struct state *st,
1039 Bitmap *upcBitmap, char *digits, int x, int y,
1040 int barY2, int guardY2)
1043 int parityPattern = upcELastDigit[charToDigit(digits[7])];
1045 int clockp = (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24);
1047 if (digits[0] == '1')
1049 parityPattern = ~parityPattern;
1053 bitmapVlin (upcBitmap, x, y, guardY2);
1054 bitmapVlin (upcBitmap, x + 2, y, guardY2);
1057 bitmapVlin (upcBitmap, x + 46 + (clockp?8:0), y, guardY2);
1058 bitmapVlin (upcBitmap, x + 48 + (clockp?8:0), y, guardY2);
1059 bitmapVlin (upcBitmap, x + 50 + (clockp?8:0), y, guardY2);
1061 /* clock kludge -- this draws an extra set of dividers after
1062 digits 2 and 4. This makes this *not* be a valid bar code,
1063 but, it looks pretty for the clock dpy.
1067 bitmapVlin (upcBitmap, x + 18, y, guardY2);
1068 bitmapVlin (upcBitmap, x + 18 + 2, y, guardY2);
1070 bitmapVlin (upcBitmap, x + 36, y, guardY2);
1071 bitmapVlin (upcBitmap, x + 36 + 2, y, guardY2);
1074 for (i = 0; i < 6; i++)
1077 (parityPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
1080 i < 4 ? 4 : /* extra spacing for clock bars */
1083 drawUpcEanDigit (upcBitmap,
1092 /* make and return a full-height UPC-E barcode */
1093 static int makeUpcEFull (struct state *st, Bitmap *dest, char *digits, int y)
1096 int baseHeight = 60;
1098 int height = baseHeight + y;
1102 drawUpcEBars (st, dest, digits, 6, y, height - 10, height - 4);
1104 drawDigitChar (st, dest, 0, height - 14, digits[0]);
1106 for (i = 0; i < 6; i++)
1108 drawDigitChar (st, dest, 11 + i*7, height - 7, digits[i+1]);
1111 drawDigitChar (st, dest, 59, height - 14, digits[7]);
1116 /* expand 8 UPC-E digits into a UPC-A number, storing into the given result
1117 * array, or just store '\0' into the first element, if the form factor
1118 * is incorrect; this will also calculate the check digit, if it is
1119 * specified as '?' */
1120 static void expandToUpcADigits (char *compressed, char *expanded)
1124 if ((compressed[0] != '0') && (compressed[0] != '1'))
1129 expanded[0] = compressed[0];
1132 expanded[11] = compressed[7];
1134 switch (compressed[6])
1140 expanded[1] = compressed[1];
1141 expanded[2] = compressed[2];
1142 expanded[3] = compressed[6];
1145 expanded[8] = compressed[3];
1146 expanded[9] = compressed[4];
1147 expanded[10] = compressed[5];
1152 expanded[1] = compressed[1];
1153 expanded[2] = compressed[2];
1154 expanded[3] = compressed[3];
1158 expanded[9] = compressed[4];
1159 expanded[10] = compressed[5];
1164 expanded[1] = compressed[1];
1165 expanded[2] = compressed[2];
1166 expanded[3] = compressed[3];
1167 expanded[4] = compressed[4];
1171 expanded[10] = compressed[5];
1176 expanded[1] = compressed[1];
1177 expanded[2] = compressed[2];
1178 expanded[3] = compressed[3];
1179 expanded[4] = compressed[4];
1180 expanded[5] = compressed[5];
1183 expanded[10] = compressed[6];
1188 if (expanded[11] == '?')
1190 unsigned int mul = 3;
1191 unsigned int sum = 0;
1193 for (i = 0; i < 11; i++)
1195 sum += charToDigit (expanded[i]) * mul;
1199 expanded[11] = ((10 - (sum % 10)) % 10) + '0';
1203 /* make and return a UPC-E barcode */
1204 static int makeUpcE (struct state *st, Bitmap *dest, char *digits, int y)
1206 char expandedDigits[13];
1207 char compressedDigits[9];
1209 expandedDigits[0] = '\0';
1210 compressedDigits[0] = '0';
1211 strcpy (compressedDigits + 1, digits);
1213 expandToUpcADigits (compressedDigits, expandedDigits);
1214 if (expandedDigits[0] == '\0')
1219 compressedDigits[7] = expandedDigits[11];
1221 return makeUpcEFull (st, dest, compressedDigits, y);
1224 /* draw the actual barcode part of a EAN-13 barcode */
1225 static void drawEan13Bars (Bitmap *upcBitmap, char *digits, int x, int y,
1226 int barY2, int guardY2)
1229 int leftPattern = ean13FirstDigit[charToDigit (digits[0])];
1232 bitmapVlin (upcBitmap, x, y, guardY2);
1233 bitmapVlin (upcBitmap, x + 2, y, guardY2);
1236 bitmapVlin (upcBitmap, x + 46, y, guardY2);
1237 bitmapVlin (upcBitmap, x + 48, y, guardY2);
1240 bitmapVlin (upcBitmap, x + 92, y, guardY2);
1241 bitmapVlin (upcBitmap, x + 94, y, guardY2);
1243 for (i = 0; i < 6; i++)
1245 UpcSet lset = (leftPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
1247 drawUpcEanDigit (upcBitmap,
1253 drawUpcEanDigit (upcBitmap,
1262 /* make and return a full-height EAN-13 barcode */
1263 static int makeEan13Full (struct state *st, Bitmap *dest, char *digits, int y)
1265 int baseWidth = 102;
1266 int baseHeight = 60;
1268 int height = baseHeight + y;
1272 drawEan13Bars (dest, digits, 6, y, height - 10, height - 4);
1274 drawDigitChar (st, dest, 0, height - 7, digits[0]);
1276 for (i = 0; i < 6; i++)
1278 drawDigitChar (st, dest, 11 + i*7, height - 7, digits[i+1]);
1279 drawDigitChar (st, dest, 57 + i*7, height - 7, digits[i+7]);
1285 /* make and return an EAN-13 barcode */
1286 static int makeEan13 (struct state *st, Bitmap *dest, char *digits, int y)
1289 unsigned int mul = 1;
1290 unsigned int sum = 0;
1292 for (i = 0; i < 12; i++)
1294 sum += charToDigit (digits[i]) * mul;
1298 if (digits[12] == '?')
1300 digits[12] = ((10 - (sum % 10)) % 10) + '0';
1303 return makeEan13Full (st, dest, digits, y);
1306 /* draw the actual barcode part of an EAN-8 barcode */
1307 static void drawEan8Bars (Bitmap *upcBitmap, char *digits, int x, int y,
1308 int barY2, int guardY2)
1313 bitmapVlin (upcBitmap, x, y, guardY2);
1314 bitmapVlin (upcBitmap, x + 2, y, guardY2);
1317 bitmapVlin (upcBitmap, x + 32, y, guardY2);
1318 bitmapVlin (upcBitmap, x + 34, y, guardY2);
1321 bitmapVlin (upcBitmap, x + 64, y, guardY2);
1322 bitmapVlin (upcBitmap, x + 66, y, guardY2);
1324 for (i = 0; i < 4; i++)
1326 drawUpcEanDigit (upcBitmap,
1332 drawUpcEanDigit (upcBitmap,
1341 /* make and return a full-height EAN-8 barcode */
1342 static int makeEan8Full (struct state *st, Bitmap *dest, char *digits, int y)
1345 int baseHeight = 60;
1347 int height = baseHeight + y;
1351 drawEan8Bars (dest, digits, 0, y, height - 10, height - 4);
1353 for (i = 0; i < 4; i++)
1355 drawDigitChar (st, dest, 5 + i*7, height - 7, digits[i]);
1356 drawDigitChar (st, dest, 37 + i*7, height - 7, digits[i+4]);
1362 /* make and return an EAN-8 barcode */
1363 static int makeEan8 (struct state *st, Bitmap *dest, char *digits, int y)
1366 unsigned int mul = 3;
1367 unsigned int sum = 0;
1369 for (i = 0; i < 7; i++)
1371 sum += charToDigit (digits[i]) * mul;
1375 if (digits[7] == '?')
1377 digits[7] = ((10 - (sum % 10)) % 10) + '0';
1380 return makeEan8Full (st, dest, digits, y);
1383 /* Dispatch to the right form factor UPC/EAN barcode generator */
1384 static void processUpcEan (struct state *st, char *str, Bitmap *dest)
1389 int supDigitCount = 0;
1391 char *banner = NULL;
1396 while ((digitCount < 15) && (supDigitCount < 7))
1399 if (((c >= '0') && (c <= '9')) || (c == '?'))
1403 supDigits[supDigitCount] = *instr;
1408 digits[digitCount] = *instr;
1428 digits[digitCount] = '\0';
1429 supDigits[supDigitCount] = '\0';
1431 if (supDigitCount == 0)
1435 else if ((supDigitCount == 2) || (supDigitCount == 5))
1437 supplement = upcEanSupplementWidth (supDigits);
1441 fprintf (stderr, "%s: invalid supplement (must be 2 or 5 digits)\n",
1455 width = makeUpcE (st, dest, digits, vstart);
1460 width = makeEan8 (st, dest, digits, vstart);
1465 width = makeUpcA (st, dest, digits, vstart);
1470 width = makeEan13 (st, dest, digits, vstart);
1475 fprintf (stderr, "%s: bad barcode (%d digits)\n",
1476 progname, digitCount);
1483 drawUpcEanSupplementalBars (st, dest, supDigits,
1485 vstart + 1, dest->height - 4, 1);
1490 bitmapDrawString5x8 (dest,
1491 (width + supplement -
1492 ((int) strlen (banner) * 5)) / 2,
1500 /* ----------------------------------------------------------------------------
1505 * overall setup stuff
1508 /* set up the system */
1509 static void setup (struct state *st)
1511 XWindowAttributes xgwa;
1514 XGetWindowAttributes (st->dpy, st->window, &xgwa);
1516 st->visual = xgwa.visual;
1517 st->cmap = xgwa.colormap;
1518 st->windowWidth = xgwa.width;
1519 st->windowHeight = xgwa.height;
1521 gcv.background = get_pixel_resource (st->dpy, xgwa.colormap,
1522 "background", "Background");
1523 gcv.foreground = get_pixel_resource (st->dpy, xgwa.colormap,
1524 "foreground", "Foreground");
1525 st->fg_pixel = gcv.foreground;
1526 st->theGC = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv);
1528 st->theBitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG, BARCODE_HEIGHT * MAX_MAG);
1529 st->theImage = XCreateImage(st->dpy, st->visual, 1, XYBitmap, 0, st->theBitmap->buf,
1530 st->theBitmap->width, st->theBitmap->height, 8,
1531 st->theBitmap->widthBytes);
1532 st->theImage->bitmap_bit_order = LSBFirst;
1533 st->theImage->byte_order = LSBFirst;
1542 /* set up the model */
1543 static void setupModel (struct state *st)
1547 st->barcode_max = 20;
1548 st->barcode_count = 0;
1549 st->barcodes = malloc (sizeof (Barcode) * st->barcode_max);
1551 for (i = 0; i < st->barcode_max; i++)
1553 st->barcodes[i].bitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG,
1554 BARCODE_HEIGHT * MAX_MAG);
1558 /* make a new barcode string */
1559 static void makeBarcodeString (struct state *st, char *str)
1563 switch ((int) (RAND_FLOAT_01 * 4))
1565 case 0: dig = 6; break;
1566 case 1: dig = 7; break;
1567 case 2: dig = 11; break;
1568 default: dig = 12; break;
1571 for (i = 0; i < dig; i++)
1573 str[i] = RAND_FLOAT_01 * 10 + '0';
1579 switch ((int) (RAND_FLOAT_01 * 3))
1581 case 0: dig = 0; break;
1582 case 1: dig = 2; break;
1583 default: dig = 5; break;
1592 str[i] = RAND_FLOAT_01 * 10 + '0';
1601 strcpy(&str[i], words[(int) (RAND_FLOAT_01 * WORD_COUNT)]);
1604 /* update the model for one iteration */
1605 static void scrollModel (struct state *st)
1609 for (i = 0; i < st->barcode_count; i++)
1611 Barcode *b = &st->barcodes[i];
1613 if ((b->x + BARCODE_WIDTH * b->mag) < 0)
1615 /* fell off the edge */
1616 if (i != (st->barcode_count - 1)) {
1617 Bitmap *oldb = b->bitmap;
1618 memmove (b, b + 1, (st->barcode_count - i - 1) * sizeof (Barcode));
1619 st->barcodes[st->barcode_count - 1].bitmap = oldb;
1621 XFreeColors (st->dpy, st->cmap, &b->pixel, 1, 0);
1625 st->barcode_count--;
1629 while (st->barcode_count < st->barcode_max)
1631 Barcode *barcode = &st->barcodes[st->barcode_count];
1632 barcode->x = (st->barcode_count == 0) ?
1634 (st->barcodes[st->barcode_count - 1].x +
1635 st->barcodes[st->barcode_count - 1].mag * BARCODE_WIDTH);
1636 barcode->x += RAND_FLOAT_01 * 100;
1637 barcode->mag = RAND_FLOAT_01 * MAX_MAG;
1639 RAND_FLOAT_01 * (st->windowHeight - BARCODE_HEIGHT * barcode->mag);
1644 makeBarcodeString(st, barcode->code);
1645 processUpcEan (st, barcode->code, st->theBitmap);
1646 bitmapScale (barcode->bitmap, st->theBitmap, barcode->mag);
1651 for (ii = 0; ii < 100; ii++)
1653 hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1654 ok = XAllocColor (st->dpy, st->cmap, &c);
1659 c.red = c.green = c.blue = 0xFFFF;
1660 if (!XAllocColor (st->dpy, st->cmap, &c))
1663 barcode->pixel = c.pixel;
1666 st->barcode_count++;
1670 /* update the model for one iteration */
1671 static void updateGrid (struct state *st)
1675 if (st->grid_w == 0 || st->grid_h == 0 ||
1676 (! (random() % 400)))
1678 XClearWindow (st->dpy, st->window);
1679 st->grid_w = 1 + (random() % 3);
1680 st->grid_h = 1 + (random() % 4);
1683 if (!st->grid_alloced_p || (! (random() % 100)))
1686 hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1687 if (st->grid_alloced_p)
1688 XFreeColors (st->dpy, st->cmap, &st->grid_pixel, 1, 0);
1689 XAllocColor (st->dpy, st->cmap, &c);
1690 st->grid_pixel = c.pixel;
1691 st->grid_alloced_p = 1;
1694 st->barcode_count = st->grid_w * st->grid_h;
1695 if (st->barcode_count > st->barcode_max) abort();
1697 for (i = 0; i < st->barcode_max; i++)
1699 Barcode *b = &st->barcodes[i];
1700 b->x = b->y = 999999;
1704 for (y = 0; y < st->grid_h; y++)
1705 for (x = 0; x < st->grid_w; x++, i++)
1707 Barcode *b = &st->barcodes[i];
1710 int cell_w = (st->windowWidth / st->grid_w);
1711 int cell_h = (st->windowHeight / st->grid_h);
1712 int mag_x = cell_w / BARCODE_WIDTH;
1713 int mag_y = cell_h / BARCODE_HEIGHT;
1714 int BW = 108 /*BARCODE_WIDTH*/;
1715 int BH = BARCODE_HEIGHT;
1717 b->mag = (mag_x < mag_y ? mag_x : mag_y);
1719 b->x = (x * cell_w) + ((cell_w - b->mag * BW) / 2);
1720 b->y = (y * cell_h) + ((cell_h - b->mag * BH) / 2);
1721 b->pixel = st->grid_pixel;
1723 if (!st->strings[i])
1726 char *s = malloc (digits + 10);
1728 for (j = 0; j < digits; j++)
1729 s[j] = (random() % 10) + '0';
1735 /* change one digit in this barcode */
1736 st->strings[i][random() % digits] = (random() % 10) + '0';
1738 strcpy (b->code, st->strings[i]);
1739 processUpcEan (st, b->code, b->bitmap);
1744 /* update the model for one iteration.
1745 This one draws a clock. By jwz. */
1746 static void updateClock (struct state *st)
1748 Barcode *b = &st->barcodes[0];
1749 int BW = 76 /* BARCODE_WIDTH */;
1750 int BH = BARCODE_HEIGHT;
1753 time_t now = time ((time_t *) 0);
1754 struct tm *tm = localtime (&now);
1755 XWindowAttributes xgwa;
1756 int ow = st->windowWidth;
1757 int oh = st->windowHeight;
1759 XGetWindowAttributes (st->dpy, st->window, &xgwa);
1760 st->windowWidth = xgwa.width;
1761 st->windowHeight = xgwa.height;
1763 mag_x = st->windowWidth / BW;
1764 mag_y = st->windowHeight / BH;
1766 st->barcode_count = 1;
1768 b->mag = (mag_x < mag_y ? mag_x : mag_y);
1770 if (b->mag > MAX_MAG) b->mag = MAX_MAG;
1771 if (b->mag < 1) b->mag = 1;
1773 b->x = (st->windowWidth - (b->mag * BW )) / 2;
1774 b->y = (st->windowHeight - (b->mag * (BH + 9))) / 2;
1775 b->pixel = st->fg_pixel;
1777 if (!st->button_down_p)
1778 sprintf (b->code, "0%02d%02d%02d?:",
1779 (st->mode == BC_CLOCK24
1789 sprintf (b->code, "0%02d%02d%02d?:",
1790 tm->tm_year % 100, tm->tm_mon+1, tm->tm_mday);
1794 int hh = BH + vstart;
1795 char expandedDigits[13];
1797 expandedDigits[0] = '\0';
1799 expandToUpcADigits (b->code, expandedDigits);
1800 if (expandedDigits[0] != '\0')
1801 b->code[7] = expandedDigits[11];
1803 bitmapClear (st->theBitmap);
1804 drawUpcEBars (st, st->theBitmap, b->code, 6, 9, 59, 65);
1805 for (i = 0; i < 6; i++)
1807 int off = (i < 2 ? 0 :
1810 drawDigitChar (st, st->theBitmap, 11 + i*7 + off, hh - 16, b->code[i+1]);
1813 if (!st->button_down_p)
1816 char *days[] = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
1817 char *s = days[tm->tm_wday];
1818 bitmapDrawString5x8 (st->theBitmap, (BW - strlen (s)*5) / 2, 0, s);
1820 drawDigitChar (st, st->theBitmap, 0, hh - 23, (tm->tm_hour < 12 ? 'A' : 'P'));
1821 drawDigitChar (st, st->theBitmap, 68, hh - 23, 'M');
1826 sprintf (s, "%03d", tm->tm_yday);
1827 bitmapDrawString5x8 (st->theBitmap, (BW - strlen (s)*5) / 2, 0, s);
1831 bitmapScale (b->bitmap, st->theBitmap, b->mag);
1833 if (ow != st->windowWidth || oh != st->windowHeight)
1834 XClearWindow (st->dpy, st->window);
1839 /* render and dpy the current model */
1840 static void renderFrame (struct state *st)
1844 for (i = 0; i < st->barcode_count; i++)
1846 Barcode *barcode = &st->barcodes[i];
1848 if (barcode->x > st->windowWidth) {
1852 /* bitmapScale (st->theBitmap, barcode->bitmap, barcode->mag);*/
1853 st->theImage->data = barcode->bitmap->buf;
1855 XSetForeground (st->dpy, st->theGC, barcode->pixel);
1856 XPutImage (st->dpy, st->window, st->theGC, st->theImage,
1857 0, 0, barcode->x, barcode->y,
1858 BARCODE_WIDTH * barcode->mag,
1859 BARCODE_HEIGHT * barcode->mag);
1863 /* do one iteration */
1864 static unsigned long
1865 barcode_draw (Display *dpy, Window win, void *closure)
1867 struct state *st = (struct state *) closure;
1868 if (st->mode == BC_SCROLL)
1870 else if (st->mode == BC_GRID)
1872 else if (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24)
1884 barcode_event (Display *dpy, Window window, void *closure, XEvent *event)
1886 struct state *st = (struct state *) closure;
1887 int clockp = (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24);
1888 if (clockp && event->xany.type == ButtonPress) {
1889 st->button_down_p = True;
1891 } else if (clockp && event->xany.type == ButtonRelease) {
1892 st->button_down_p = False;
1899 barcode_reshape (Display *dpy, Window window, void *closure,
1900 unsigned int w, unsigned int h)
1902 struct state *st = (struct state *) closure;
1903 st->windowWidth = w;
1904 st->windowHeight = h;
1908 barcode_free (Display *dpy, Window window, void *closure)
1913 /* main and options and stuff */
1915 static const char *barcode_defaults [] = {
1916 ".background: black",
1917 ".foreground: green",
1924 static XrmOptionDescRec barcode_options [] = {
1925 { "-delay", ".delay", XrmoptionSepArg, 0 },
1926 { "-mode", ".mode", XrmoptionSepArg, 0 },
1927 { "-scroll", ".mode", XrmoptionNoArg, "scroll" },
1928 { "-grid", ".mode", XrmoptionNoArg, "grid" },
1929 { "-clock", ".mode", XrmoptionNoArg, "clock" },
1930 { "-clock12", ".mode", XrmoptionNoArg, "clock12" },
1931 { "-clock24", ".mode", XrmoptionNoArg, "clock24" },
1935 /* initialize the user-specifiable params */
1936 static void initParams (struct state *st)
1941 st->delay = get_integer_resource (st->dpy, "delay", "Delay");
1944 fprintf (stderr, "%s: delay must be at least 0\n", progname);
1948 s = get_string_resource (st->dpy, "mode", "Mode");
1949 if (!s || !*s || !strcasecmp (s, "scroll"))
1950 st->mode = BC_SCROLL;
1951 else if (!strcasecmp (s, "grid"))
1953 else if (!strcasecmp (s, "clock") ||
1954 !strcasecmp (s, "clock12"))
1955 st->mode = BC_CLOCK12;
1956 else if (!strcasecmp (s, "clock24"))
1957 st->mode = BC_CLOCK24;
1960 fprintf (stderr, "%s: unknown mode \"%s\"\n", progname, s);
1965 if (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24)
1966 st->delay = 10000; /* only update every 1/10th second */
1975 barcode_init (Display *dpy, Window win)
1977 struct state *st = (struct state *) calloc (1, sizeof(*st));
1988 XSCREENSAVER_MODULE ("Barcode", barcode)