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 if (st->windowWidth < 100 || st->windowHeight < 100) {
1640 barcode->mag *= 0.5;
1641 if (barcode->mag <= 0) barcode->mag = 1;
1645 RAND_FLOAT_01 * (st->windowHeight - BARCODE_HEIGHT * barcode->mag);
1650 makeBarcodeString(st, barcode->code);
1651 processUpcEan (st, barcode->code, st->theBitmap);
1652 bitmapScale (barcode->bitmap, st->theBitmap, barcode->mag);
1657 for (ii = 0; ii < 100; ii++)
1659 hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1660 ok = XAllocColor (st->dpy, st->cmap, &c);
1665 c.red = c.green = c.blue = 0xFFFF;
1666 if (!XAllocColor (st->dpy, st->cmap, &c))
1669 barcode->pixel = c.pixel;
1672 st->barcode_count++;
1676 /* update the model for one iteration */
1677 static void updateGrid (struct state *st)
1681 if (st->grid_w == 0 || st->grid_h == 0 ||
1682 (! (random() % 400)))
1684 XClearWindow (st->dpy, st->window);
1685 st->grid_w = 1 + (random() % 3);
1686 st->grid_h = 1 + (random() % 4);
1689 if (!st->grid_alloced_p || (! (random() % 100)))
1692 hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1693 if (st->grid_alloced_p)
1694 XFreeColors (st->dpy, st->cmap, &st->grid_pixel, 1, 0);
1695 XAllocColor (st->dpy, st->cmap, &c);
1696 st->grid_pixel = c.pixel;
1697 st->grid_alloced_p = 1;
1700 st->barcode_count = st->grid_w * st->grid_h;
1701 if (st->barcode_count > st->barcode_max) abort();
1703 for (i = 0; i < st->barcode_max; i++)
1705 Barcode *b = &st->barcodes[i];
1706 b->x = b->y = 999999;
1710 for (y = 0; y < st->grid_h; y++)
1711 for (x = 0; x < st->grid_w; x++, i++)
1713 Barcode *b = &st->barcodes[i];
1716 int cell_w = (st->windowWidth / st->grid_w);
1717 int cell_h = (st->windowHeight / st->grid_h);
1718 int mag_x = cell_w / BARCODE_WIDTH;
1719 int mag_y = cell_h / BARCODE_HEIGHT;
1720 int BW = 108 /*BARCODE_WIDTH*/;
1721 int BH = BARCODE_HEIGHT;
1723 b->mag = (mag_x < mag_y ? mag_x : mag_y);
1725 b->x = (x * cell_w) + ((cell_w - b->mag * BW) / 2);
1726 b->y = (y * cell_h) + ((cell_h - b->mag * BH) / 2);
1727 b->pixel = st->grid_pixel;
1729 if (!st->strings[i])
1732 char *s = malloc (digits + 10);
1734 for (j = 0; j < digits; j++)
1735 s[j] = (random() % 10) + '0';
1741 /* change one digit in this barcode */
1742 st->strings[i][random() % digits] = (random() % 10) + '0';
1744 strcpy (b->code, st->strings[i]);
1745 processUpcEan (st, b->code, b->bitmap);
1750 /* update the model for one iteration.
1751 This one draws a clock. By jwz. */
1752 static void updateClock (struct state *st)
1754 Barcode *b = &st->barcodes[0];
1755 int BW = 76 /* BARCODE_WIDTH */;
1756 int BH = BARCODE_HEIGHT;
1759 time_t now = time ((time_t *) 0);
1760 struct tm *tm = localtime (&now);
1761 XWindowAttributes xgwa;
1762 int ow = st->windowWidth;
1763 int oh = st->windowHeight;
1765 XGetWindowAttributes (st->dpy, st->window, &xgwa);
1766 st->windowWidth = xgwa.width;
1767 st->windowHeight = xgwa.height;
1769 mag_x = st->windowWidth / BW;
1770 mag_y = st->windowHeight / BH;
1772 st->barcode_count = 1;
1774 b->mag = (mag_x < mag_y ? mag_x : mag_y);
1776 if (b->mag > MAX_MAG) b->mag = MAX_MAG;
1777 if (b->mag < 1) b->mag = 1;
1779 b->x = (st->windowWidth - (b->mag * BW )) / 2;
1780 b->y = (st->windowHeight - (b->mag * (BH + 9))) / 2;
1781 b->pixel = st->fg_pixel;
1783 if (!st->button_down_p)
1784 sprintf (b->code, "0%02d%02d%02d?:",
1785 (st->mode == BC_CLOCK24
1795 sprintf (b->code, "0%02d%02d%02d?:",
1796 tm->tm_year % 100, tm->tm_mon+1, tm->tm_mday);
1800 int hh = BH + vstart;
1801 char expandedDigits[13];
1803 expandedDigits[0] = '\0';
1805 expandToUpcADigits (b->code, expandedDigits);
1806 if (expandedDigits[0] != '\0')
1807 b->code[7] = expandedDigits[11];
1809 bitmapClear (st->theBitmap);
1810 drawUpcEBars (st, st->theBitmap, b->code, 6, 9, 59, 65);
1811 for (i = 0; i < 6; i++)
1813 int off = (i < 2 ? 0 :
1816 drawDigitChar (st, st->theBitmap, 11 + i*7 + off, hh - 16, b->code[i+1]);
1819 if (!st->button_down_p)
1822 char *days[] = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
1823 char *s = days[tm->tm_wday];
1824 bitmapDrawString5x8 (st->theBitmap, (BW - strlen (s)*5) / 2, 0, s);
1826 drawDigitChar (st, st->theBitmap, 0, hh - 23, (tm->tm_hour < 12 ? 'A' : 'P'));
1827 drawDigitChar (st, st->theBitmap, 68, hh - 23, 'M');
1832 sprintf (s, "%03d", tm->tm_yday);
1833 bitmapDrawString5x8 (st->theBitmap, (BW - strlen (s)*5) / 2, 0, s);
1837 bitmapScale (b->bitmap, st->theBitmap, b->mag);
1839 if (ow != st->windowWidth || oh != st->windowHeight)
1840 XClearWindow (st->dpy, st->window);
1845 /* render and dpy the current model */
1846 static void renderFrame (struct state *st)
1850 for (i = 0; i < st->barcode_count; i++)
1852 Barcode *barcode = &st->barcodes[i];
1854 if (barcode->x > st->windowWidth) {
1858 /* bitmapScale (st->theBitmap, barcode->bitmap, barcode->mag);*/
1859 st->theImage->data = barcode->bitmap->buf;
1861 XSetForeground (st->dpy, st->theGC, barcode->pixel);
1862 XPutImage (st->dpy, st->window, st->theGC, st->theImage,
1863 0, 0, barcode->x, barcode->y,
1864 BARCODE_WIDTH * barcode->mag,
1865 BARCODE_HEIGHT * barcode->mag);
1869 /* do one iteration */
1870 static unsigned long
1871 barcode_draw (Display *dpy, Window win, void *closure)
1873 struct state *st = (struct state *) closure;
1874 if (st->mode == BC_SCROLL)
1876 else if (st->mode == BC_GRID)
1878 else if (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24)
1890 barcode_event (Display *dpy, Window window, void *closure, XEvent *event)
1892 struct state *st = (struct state *) closure;
1893 int clockp = (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24);
1894 if (clockp && event->xany.type == ButtonPress) {
1895 st->button_down_p = True;
1897 } else if (clockp && event->xany.type == ButtonRelease) {
1898 st->button_down_p = False;
1905 barcode_reshape (Display *dpy, Window window, void *closure,
1906 unsigned int w, unsigned int h)
1908 struct state *st = (struct state *) closure;
1909 st->windowWidth = w;
1910 st->windowHeight = h;
1914 barcode_free (Display *dpy, Window window, void *closure)
1919 /* main and options and stuff */
1921 static const char *barcode_defaults [] = {
1922 ".background: black",
1923 ".foreground: green",
1931 static XrmOptionDescRec barcode_options [] = {
1932 { "-delay", ".delay", XrmoptionSepArg, 0 },
1933 { "-mode", ".mode", XrmoptionSepArg, 0 },
1934 { "-scroll", ".mode", XrmoptionNoArg, "scroll" },
1935 { "-grid", ".mode", XrmoptionNoArg, "grid" },
1936 { "-clock", ".mode", XrmoptionNoArg, "clock" },
1937 { "-clock12", ".mode", XrmoptionNoArg, "clock12" },
1938 { "-clock24", ".mode", XrmoptionNoArg, "clock24" },
1942 /* initialize the user-specifiable params */
1943 static void initParams (struct state *st)
1948 st->delay = get_integer_resource (st->dpy, "delay", "Delay");
1951 fprintf (stderr, "%s: delay must be at least 0\n", progname);
1955 s = get_string_resource (st->dpy, "mode", "Mode");
1956 if (!s || !*s || !strcasecmp (s, "scroll"))
1957 st->mode = BC_SCROLL;
1958 else if (!strcasecmp (s, "grid"))
1960 else if (!strcasecmp (s, "clock") ||
1961 !strcasecmp (s, "clock12"))
1962 st->mode = BC_CLOCK12;
1963 else if (!strcasecmp (s, "clock24"))
1964 st->mode = BC_CLOCK24;
1967 fprintf (stderr, "%s: unknown mode \"%s\"\n", progname, s);
1972 if (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24)
1973 st->delay = 10000; /* only update every 1/10th second */
1982 barcode_init (Display *dpy, Window win)
1984 struct state *st = (struct state *) calloc (1, sizeof(*st));
1995 XSCREENSAVER_MODULE ("Barcode", barcode)