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[] =
358 #define WORD_COUNT (sizeof(words) / sizeof(char *))
362 /* ----------------------------------------------------------------------------
363 * bitmap manipulation
366 /* construct a new bitmap */
367 static Bitmap *makeBitmap (int width, int height)
369 Bitmap *result = malloc (sizeof (Bitmap));
370 result->width = width;
371 result->height = height;
372 result->widthBytes = (width + 7) / 8;
373 result->buf = calloc (1, height * result->widthBytes);
378 static void bitmapClear (Bitmap *b)
380 memset (b->buf, 0, b->widthBytes * b->height);
385 static void bitmapFree (Bitmap *b)
393 /* get the byte value at the given byte-offset coordinates in the given
395 static int bitmapGetByte (Bitmap *b, int xByte, int y)
398 (xByte >= b->widthBytes) ||
402 /* out-of-range get returns 0 */
406 return b->buf[b->widthBytes * y + xByte];
409 /* get the bit value at the given coordinates in the given bitmap */
410 static int bitmapGet (Bitmap *b, int x, int y)
414 int byteValue = bitmapGetByte (b, xbyte, y);
416 return (byteValue & (1 << xbit)) >> xbit;
419 /* set the bit value at the given coordinates in the given bitmap */
420 static void bitmapSet (Bitmap *b, int x, int y, int value)
430 /* ignore out-of-range set */
436 b->buf[b->widthBytes * y + xbyte] |= 1 << xbit;
440 b->buf[b->widthBytes * y + xbyte] &= ~(1 << xbit);
444 /* copy the given rectangle to the given destination from the given source. */
445 static void bitmapCopyRect (Bitmap *dest, int dx, int dy,
446 Bitmap *src, int sx, int sy, int width, int height)
450 for (y = 0; y < height; y++)
452 for (x = 0; x < width; x++)
454 bitmapSet (dest, x + dx, y + dy, bitmapGet (src, x + sx, y + sy));
459 /* draw a vertical line in the given bitmap */
460 static void bitmapVlin (Bitmap *b, int x, int y1, int y2)
464 bitmapSet (b, x, y1, 1);
469 /* scale a bitmap into another bitmap */
470 static void bitmapScale (Bitmap *dest, Bitmap *src, int mag)
474 for (y = 0; y < BARCODE_HEIGHT; y++)
476 for (x = 0; x < BARCODE_WIDTH; x++)
478 int v = bitmapGet (src, x, y);
479 for (x2 = 0; x2 < mag; x2++)
481 for (y2 = 0; y2 < mag; y2++)
483 bitmapSet (dest, x * mag + x2, y * mag + y2, v);
491 /* ----------------------------------------------------------------------------
492 * character generation
495 static unsigned char font5x8Buf[] =
497 0x1e, 0x01, 0x06, 0x01, 0x1e, 0x00, 0x1e, 0x01, 0x06, 0x01, 0x1e, 0x00,
498 0x1e, 0x01, 0x1e, 0x01, 0x1e, 0x00, 0x01, 0x00, 0x1f, 0x08, 0x04, 0x08,
499 0x1f, 0x00, 0x11, 0x1f, 0x11, 0x00, 0x1f, 0x01, 0x01, 0x00, 0x1f, 0x04,
500 0x0a, 0x11, 0x00, 0x01, 0x00, 0x0e, 0x11, 0x11, 0x00, 0x0e, 0x11, 0x11,
501 0x0e, 0x00, 0x1f, 0x08, 0x04, 0x08, 0x1f, 0x00, 0x44, 0x41, 0x4e, 0x20,
502 0x42, 0x4f, 0x52, 0x4e, 0x53, 0x54, 0x45, 0x49, 0x4e, 0x21, 0x21, 0x00,
503 0x66, 0x6e, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
504 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
505 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
506 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
507 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
508 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
509 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
510 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
511 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
512 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
513 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x05, 0x05, 0x00,
520 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x00,
521 0x02, 0x0f, 0x01, 0x0f, 0x08, 0x0f, 0x04, 0x00, 0x0b, 0x0b, 0x08, 0x06,
522 0x01, 0x0d, 0x0d, 0x00, 0x03, 0x05, 0x02, 0x05, 0x0d, 0x05, 0x0b, 0x00,
523 0x04, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x02,
524 0x02, 0x02, 0x04, 0x00, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x00,
525 0x00, 0x09, 0x06, 0x0f, 0x06, 0x09, 0x00, 0x00, 0x00, 0x02, 0x02, 0x07,
526 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x06, 0x00,
527 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x04, 0x06, 0x02, 0x01, 0x01, 0x00,
529 0x0f, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x06, 0x04, 0x04, 0x04,
530 0x04, 0x04, 0x0f, 0x00, 0x0f, 0x09, 0x08, 0x0f, 0x01, 0x09, 0x0f, 0x00,
531 0x0f, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x0f, 0x00, 0x09, 0x09, 0x09, 0x0f,
532 0x08, 0x08, 0x08, 0x00, 0x0f, 0x09, 0x01, 0x0f, 0x08, 0x09, 0x0f, 0x00,
533 0x03, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0c,
534 0x04, 0x04, 0x04, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x0f, 0x00,
535 0x0f, 0x09, 0x09, 0x0f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00,
536 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x04, 0x06, 0x00,
537 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x0f, 0x00,
538 0x0f, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x04, 0x02, 0x01, 0x00,
539 0x0f, 0x09, 0x08, 0x0e, 0x02, 0x00, 0x02, 0x00, 0x0f, 0x09, 0x0d, 0x0d,
540 0x0d, 0x01, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x09, 0x00,
541 0x07, 0x09, 0x09, 0x07, 0x09, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x01, 0x01,
542 0x01, 0x01, 0x0f, 0x00, 0x07, 0x09, 0x09, 0x09, 0x09, 0x09, 0x07, 0x00,
543 0x0f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x0f, 0x00, 0x0f, 0x01, 0x01, 0x0f,
544 0x01, 0x01, 0x01, 0x00, 0x0f, 0x01, 0x01, 0x0d, 0x09, 0x09, 0x0f, 0x00,
545 0x09, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x09, 0x00, 0x07, 0x02, 0x02, 0x02,
546 0x02, 0x02, 0x07, 0x00, 0x0e, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x00,
547 0x09, 0x09, 0x09, 0x07, 0x09, 0x09, 0x09, 0x00, 0x01, 0x01, 0x01, 0x01,
548 0x01, 0x01, 0x0f, 0x00, 0x09, 0x0f, 0x0f, 0x0f, 0x09, 0x09, 0x09, 0x00,
549 0x09, 0x0b, 0x0d, 0x09, 0x09, 0x09, 0x09, 0x00, 0x0f, 0x09, 0x09, 0x09,
550 0x09, 0x09, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x01, 0x01, 0x01, 0x00,
551 0x0f, 0x09, 0x09, 0x09, 0x0b, 0x05, 0x0b, 0x00, 0x07, 0x09, 0x09, 0x07,
552 0x09, 0x09, 0x09, 0x00, 0x0f, 0x01, 0x01, 0x0f, 0x08, 0x08, 0x0f, 0x00,
553 0x0f, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x09, 0x09, 0x09, 0x09,
554 0x09, 0x09, 0x0f, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x05, 0x02, 0x00,
555 0x09, 0x09, 0x09, 0x09, 0x0f, 0x0f, 0x09, 0x00, 0x09, 0x09, 0x05, 0x06,
556 0x0a, 0x09, 0x09, 0x00, 0x09, 0x09, 0x09, 0x0f, 0x08, 0x08, 0x0f, 0x00,
557 0x0f, 0x08, 0x08, 0x06, 0x01, 0x01, 0x0f, 0x00, 0x0e, 0x02, 0x02, 0x02,
558 0x02, 0x02, 0x0e, 0x00, 0x01, 0x01, 0x02, 0x06, 0x04, 0x08, 0x08, 0x00,
559 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x00, 0x02, 0x05, 0x05, 0x00,
560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
561 0x02, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08,
562 0x0f, 0x09, 0x0f, 0x00, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x09, 0x0f, 0x00,
563 0x00, 0x00, 0x0f, 0x01, 0x01, 0x01, 0x0f, 0x00, 0x08, 0x08, 0x0f, 0x09,
564 0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x09, 0x0f, 0x01, 0x0f, 0x00,
565 0x0e, 0x02, 0x0f, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x09,
566 0x09, 0x0f, 0x08, 0x0c, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x09, 0x09, 0x00,
567 0x02, 0x00, 0x03, 0x02, 0x02, 0x02, 0x07, 0x00, 0x04, 0x00, 0x04, 0x04,
568 0x04, 0x04, 0x05, 0x07, 0x01, 0x01, 0x09, 0x05, 0x03, 0x05, 0x09, 0x00,
569 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x00, 0x00, 0x09, 0x0f,
570 0x0f, 0x09, 0x09, 0x00, 0x00, 0x00, 0x0f, 0x09, 0x09, 0x09, 0x09, 0x00,
571 0x00, 0x00, 0x0f, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x09,
572 0x09, 0x0f, 0x01, 0x01, 0x00, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x08, 0x08,
573 0x00, 0x00, 0x0f, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x01,
574 0x0f, 0x08, 0x0f, 0x00, 0x00, 0x02, 0x0f, 0x02, 0x02, 0x02, 0x0e, 0x00,
575 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x09, 0x09,
576 0x09, 0x05, 0x02, 0x00, 0x00, 0x00, 0x09, 0x09, 0x0f, 0x0f, 0x09, 0x00,
577 0x00, 0x00, 0x09, 0x09, 0x06, 0x09, 0x09, 0x00, 0x00, 0x00, 0x09, 0x09,
578 0x09, 0x0f, 0x08, 0x0c, 0x00, 0x00, 0x0f, 0x08, 0x06, 0x01, 0x0f, 0x00,
579 0x08, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08, 0x00, 0x02, 0x02, 0x02, 0x02,
580 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x04, 0x02, 0x02, 0x01, 0x00,
581 0x00, 0x0a, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
582 0x0f, 0x0f, 0x0f, 0x00
585 static Bitmap font5x8 = { 8, 1024, 1, (char *) font5x8Buf };
587 /* draw the given 5x8 character at the given coordinates */
588 static void bitmapDrawChar5x8 (Bitmap *b, int x, int y, char c)
590 bitmapCopyRect (b, x, y, &font5x8, 0, c * 8, 5, 8);
593 /* draw a string of 5x8 characters at the given coordinates */
594 static void bitmapDrawString5x8 (Bitmap *b, int x, int y, char *str)
613 bitmapDrawChar5x8 (b, x, y, c);
622 /* ----------------------------------------------------------------------------
623 * upc/ean symbologies
626 /* A quick lesson in UPC and EAN barcodes:
628 * Each digit consists of 2 bars and 2 spaces, taking a total width of 7
629 * times the width of the thinnest possible bar or space. There are three
630 * different possible representations for each digit, used depending on
631 * what side of a two-sided barcode the digit is used on, and to encode
632 * checksum or other information in some cases. The three forms are
633 * related. Taking as the "base" form the pattern as seen on the right-hand
634 * side of a UPC-A barcode, the other forms are the inverse of the base
635 * (that is, bar becomes space and vice versa) and the mirror image of the
636 * base. Still confused? Here's a complete table, where 0 means space and 1
639 * Left-A Left-B Right
640 * ------- ------- -------
641 * 0 0001101 0100111 1110010
642 * 1 0011001 0110011 1100110
643 * 2 0010011 0011011 1101100
644 * 3 0111101 0100001 1000010
645 * 4 0100011 0011101 1011100
646 * 5 0110001 0111001 1001110
647 * 6 0101111 0000101 1010000
648 * 7 0111011 0010001 1000100
649 * 8 0110111 0001001 1001000
650 * 9 0001011 0010111 1110100
652 * A UPC-A barcode consists of 6 patterns from Left-A on the left-hand side,
653 * 6 patterns from Right on the right-hand side, a guard pattern of 01010
654 * in the middle, and a guard pattern of 101 on each end. The 12th digit
655 * checksum is calculated as follows: Take the 1st, 3rd, ... 11th digits,
656 * sum them and multiplying by 3, and add that to the sum of the other digits.
657 * Subtract the final digit from 10, and that is the checksum digit. (If
658 * the last digit of the sum is 0, then the check digit is 0.)
660 * An EAN-13 barcode is just like a UPC-A barcode, except that the characters
661 * on the left-hand side have a pattern of Left-A and Left-B that encodes
662 * an extra first digit. Note that an EAN-13 barcode with the first digit
663 * of 0 is exactly the same as the UPC-A barcode of the rightmost 12 digits.
664 * The patterns to encode the first digit are as follows:
681 * The checksum for EAN-13 is just like UPC-A, except the 2nd, 4th, ... 12th
682 * digits are multiplied by 3 instead of the other way around.
684 * An EAN-8 barcode is just like a UPC-A barcode, except there are only 4
685 * digits in each half. Unlike EAN-13, there's no nonsense about different
686 * left-hand side patterns, either.
688 * A UPC-E barcode contains 6 explicit characters between a guard of 101
689 * on the left and 010101 on the right. The explicit characters are the
690 * middle six characters of the code. The first and last characters are
691 * encoded in the parity pattern of the six characters. There are two
692 * sets of parity patterns, one to use if the first digit of the number
693 * is 0, and another if it is 1. (UPC-E barcodes may only start with a 0
694 * or 1.) The patterns are as follows:
696 * First digit 0 First digit 1
697 * Explicit Digit Explicit Digit
699 * 1 2 3 4 5 6 1 2 3 4 5 6
700 * - - - - - - - - - - - -
701 * 0 b b b a a a a a a b b b
702 * 1 b b a b a a a a b a b b
703 * 2 b b a a b a a a b b a b
704 * 3 b b a a a b a a b b b a
705 * 4 b a b b a a a b a a b b
706 * 5 b a a b b a a b b a a b
707 * 6 b a a a b b a b b b a a
708 * 7 b a b a b a a b a b a b
709 * 8 b a b a a b a b a b b a
710 * 9 b a a b a b a b b a b a
712 * (Note that the two sets are the complements of each other. Also note
713 * that the first digit 1 patterns are mostly the same as the EAN-13
714 * first digit patterns.) The UPC-E check digit (the final digit encoded in
715 * the parity pattern) is the same as the UPC-A check digit for the
716 * expanded form of the UPC-E number. The expanstion is as follows, based
717 * on the last explicit digit (the second to last digit) in the encoded
721 * UPC-E form UPC-A form
722 * ---------- -------------
723 * XABCDE0Y XAB00000CDEY
724 * XABCDE1Y XAB10000CDEY
725 * XABCDE2Y XAB20000CDEY
726 * XABCDE3Y XABC00000DEY
727 * XABCDE4Y XABCD00000EY
728 * XABCDE5Y XABCDE00005Y
729 * XABCDE6Y XABCDE00006Y
730 * XABCDE7Y XABCDE00007Y
731 * XABCDE8Y XABCDE00008Y
732 * XABCDE9Y XABCDE00009Y
734 * All UPC/EAN barcodes may have an additional 2- or 5-digit supplemental
735 * code just to the right of the main barcode. The supplement starts about
736 * one digit-length (that is about 7 times the width of the thinnest bar)
737 * to the right of the main code, beginning with the guard pattern 1011.
738 * After that comes each digit, with a guard pattern of 01 between each,
739 * but not at the end. The digits are encoded using the left A and B
740 * characters to encode a parity pattern.
742 * For 2-digit supplements, the parity pattern is determined by the
743 * lower two bits of the numeric value of the code (e.g., 42 would use
746 * Lower 2 bits Parity Pattern
747 * ------------ --------------
753 * For 5-digit supplements, the parity pattern is calculated in a similar
754 * manner to check digit calculation: The first, third, and fifth digits
755 * are summed and multiplied by 3; the second and fourth digits are summed
756 * and multiplied by nine; the parity digit is the sum of those two numbers,
757 * modulo 10. The parity pattern is then the last five patterns from the
758 * UPC-E final digit 0 table for the corresponding digit.
761 /* enum to indicate which pattern set to use */
764 UPC_LEFT_A, UPC_LEFT_B, UPC_RIGHT
768 /* the Left A patterns */
769 static unsigned int upcLeftA[] = {
770 0x0d, 0x19, 0x13, 0x3d, 0x23, 0x31, 0x2f, 0x3b, 0x37, 0x0b
773 /* the Left B patterns */
774 static unsigned int upcLeftB[] = {
775 0x27, 0x33, 0x1b, 0x21, 0x1d, 0x39, 0x05, 0x11, 0x09, 0x17
778 /* the Right patterns */
779 static unsigned int upcRight[] = {
780 0x72, 0x66, 0x6c, 0x42, 0x5c, 0x4e, 0x50, 0x44, 0x48, 0x74
783 /* the EAN-13 first-digit patterns */
784 static unsigned int ean13FirstDigit[] = {
785 0x00, 0x0b, 0x0d, 0x0e, 0x13, 0x19, 0x1c, 0x15, 0x16, 0x1a
788 /* the UPC-E last-digit patterns for first digit 0 (complement for
789 * digit 1); also used for 5-digit supplemental check patterns */
790 static unsigned int upcELastDigit[] = {
791 0x38, 0x34, 0x32, 0x31, 0x2c, 0x26, 0x23, 0x2a, 0x29, 0x25
794 /* turn a character into an int representing its digit value; return
795 * 0 for things not in the range '0'-'9' */
796 static int charToDigit (char c)
798 if ((c >= '0') && (c <= '9'))
808 /* draw the given digit character at the given coordinates; a '0' is
809 * used in place of any non-digit character */
810 static void drawDigitChar (struct state *st, Bitmap *b, int x, int y, char c)
812 if (st->mode != BC_CLOCK24 &&
813 st->mode != BC_CLOCK12)
814 if ((c < '0') || (c > '9'))
817 bitmapDrawChar5x8 (b, x, y, c);
820 /* draw a upc/ean digit at the given coordinates */
821 static void drawUpcEanDigit (Bitmap *upcBitmap, int x, int y1, int y2, char n,
831 bits = upcLeftA[(int) n];
834 bits = upcLeftB[(int) n];
836 default /* case UPC_RIGHT */:
837 bits = upcRight[(int) n];
841 for (i = 6; i >=0; i--)
845 bitmapVlin (upcBitmap, x, y1, y2);
851 /* report the width of the given supplemental code or 0 if it is a bad
853 static int upcEanSupplementWidth (char *digits)
855 switch (strlen (digits))
857 case 2: return 28; /* 8 + 4 + 2*7 + 1*2 */
858 case 5: return 55; /* 8 + 4 + 5*7 + 4*2 */
863 /* draw the given supplemental barcode, including the textual digits */
864 static void drawUpcEanSupplementalBars (struct state *st,
865 Bitmap *upcBitmap, char *digits,
866 int x, int y, int y2, int textAbove)
868 int len = strlen (digits);
885 x += 8; /* skip the space between the main and supplemental */
892 parity = (charToDigit (digits[0]) * 10 +
893 charToDigit (digits[1])) & 0x3;
900 ((charToDigit (digits[0]) + charToDigit (digits[2]) +
901 charToDigit (digits[4])) * 3
902 + (charToDigit (digits[1]) + charToDigit (digits[3])) * 9)
904 parity = upcELastDigit[parity];
909 fprintf (stderr, "%s: bad supplement (%d digits)\n",
917 bitmapVlin (upcBitmap, x, y, y2);
918 bitmapVlin (upcBitmap, x + 2, y, y2);
919 bitmapVlin (upcBitmap, x + 3, y, y2);
921 for (i = 0; i < len; i++)
924 (parity & (1 << (len - 1 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
925 int baseX = x + 2 + i * 9;
927 /* separator / end of header */
930 bitmapVlin (upcBitmap, baseX, y, y2);
932 bitmapVlin (upcBitmap, baseX + 1, y, y2);
934 drawUpcEanDigit (upcBitmap,
941 drawDigitChar (st, upcBitmap, textX + i*6, textY, digits[i]);
945 /* draw the actual barcode part of a UPC-A barcode */
946 static void drawUpcABars (Bitmap *upcBitmap, char *digits, int x, int y,
947 int barY2, int guardY2)
952 bitmapVlin (upcBitmap, x, y, guardY2);
953 bitmapVlin (upcBitmap, x + 2, y, guardY2);
956 bitmapVlin (upcBitmap, x + 46, y, guardY2);
957 bitmapVlin (upcBitmap, x + 48, y, guardY2);
960 bitmapVlin (upcBitmap, x + 92, y, guardY2);
961 bitmapVlin (upcBitmap, x + 94, y, guardY2);
963 for (i = 0; i < 6; i++)
965 drawUpcEanDigit (upcBitmap,
968 (i == 0) ? guardY2 : barY2,
971 drawUpcEanDigit (upcBitmap,
974 (i == 5) ? guardY2 : barY2,
980 /* make and return a full-height UPC-A barcode */
981 static int makeUpcAFull (struct state *st, Bitmap *dest, char *digits, int y)
986 int height = baseHeight + y;
990 drawUpcABars (dest, digits, 6, y, height - 10, height - 4);
992 drawDigitChar (st, dest, 0, height - 14, digits[0]);
994 for (i = 0; i < 5; i++)
996 drawDigitChar (st, dest, 18 + i*7, height - 7, digits[i+1]);
997 drawDigitChar (st, dest, 57 + i*7, height - 7, digits[i+6]);
1000 drawDigitChar (st, dest, 103, height - 14, digits[11]);
1005 /* make and return a UPC-A barcode */
1006 static int makeUpcA (struct state *st, Bitmap *dest, char *digits, int y)
1009 unsigned int mul = 3;
1010 unsigned int sum = 0;
1012 for (i = 0; i < 11; i++)
1014 sum += charToDigit (digits[i]) * mul;
1018 if (digits[11] == '?')
1020 digits[11] = ((10 - (sum % 10)) % 10) + '0';
1023 return makeUpcAFull (st, dest, digits, y);
1026 /* draw the actual barcode part of a UPC-E barcode */
1027 static void drawUpcEBars (struct state *st,
1028 Bitmap *upcBitmap, char *digits, int x, int y,
1029 int barY2, int guardY2)
1032 int parityPattern = upcELastDigit[charToDigit(digits[7])];
1034 int clockp = (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24);
1036 if (digits[0] == '1')
1038 parityPattern = ~parityPattern;
1042 bitmapVlin (upcBitmap, x, y, guardY2);
1043 bitmapVlin (upcBitmap, x + 2, y, guardY2);
1046 bitmapVlin (upcBitmap, x + 46 + (clockp?8:0), y, guardY2);
1047 bitmapVlin (upcBitmap, x + 48 + (clockp?8:0), y, guardY2);
1048 bitmapVlin (upcBitmap, x + 50 + (clockp?8:0), y, guardY2);
1050 /* clock kludge -- this draws an extra set of dividers after
1051 digits 2 and 4. This makes this *not* be a valid bar code,
1052 but, it looks pretty for the clock dpy.
1056 bitmapVlin (upcBitmap, x + 18, y, guardY2);
1057 bitmapVlin (upcBitmap, x + 18 + 2, y, guardY2);
1059 bitmapVlin (upcBitmap, x + 36, y, guardY2);
1060 bitmapVlin (upcBitmap, x + 36 + 2, y, guardY2);
1063 for (i = 0; i < 6; i++)
1066 (parityPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
1069 i < 4 ? 4 : /* extra spacing for clock bars */
1072 drawUpcEanDigit (upcBitmap,
1081 /* make and return a full-height UPC-E barcode */
1082 static int makeUpcEFull (struct state *st, Bitmap *dest, char *digits, int y)
1085 int baseHeight = 60;
1087 int height = baseHeight + y;
1091 drawUpcEBars (st, dest, digits, 6, y, height - 10, height - 4);
1093 drawDigitChar (st, dest, 0, height - 14, digits[0]);
1095 for (i = 0; i < 6; i++)
1097 drawDigitChar (st, dest, 11 + i*7, height - 7, digits[i+1]);
1100 drawDigitChar (st, dest, 59, height - 14, digits[7]);
1105 /* expand 8 UPC-E digits into a UPC-A number, storing into the given result
1106 * array, or just store '\0' into the first element, if the form factor
1107 * is incorrect; this will also calculate the check digit, if it is
1108 * specified as '?' */
1109 static void expandToUpcADigits (char *compressed, char *expanded)
1113 if ((compressed[0] != '0') && (compressed[0] != '1'))
1118 expanded[0] = compressed[0];
1121 expanded[11] = compressed[7];
1123 switch (compressed[6])
1129 expanded[1] = compressed[1];
1130 expanded[2] = compressed[2];
1131 expanded[3] = compressed[6];
1134 expanded[8] = compressed[3];
1135 expanded[9] = compressed[4];
1136 expanded[10] = compressed[5];
1141 expanded[1] = compressed[1];
1142 expanded[2] = compressed[2];
1143 expanded[3] = compressed[3];
1147 expanded[9] = compressed[4];
1148 expanded[10] = compressed[5];
1153 expanded[1] = compressed[1];
1154 expanded[2] = compressed[2];
1155 expanded[3] = compressed[3];
1156 expanded[4] = compressed[4];
1160 expanded[10] = compressed[5];
1165 expanded[1] = compressed[1];
1166 expanded[2] = compressed[2];
1167 expanded[3] = compressed[3];
1168 expanded[4] = compressed[4];
1169 expanded[5] = compressed[5];
1172 expanded[10] = compressed[6];
1177 if (expanded[11] == '?')
1179 unsigned int mul = 3;
1180 unsigned int sum = 0;
1182 for (i = 0; i < 11; i++)
1184 sum += charToDigit (expanded[i]) * mul;
1188 expanded[11] = ((10 - (sum % 10)) % 10) + '0';
1192 /* make and return a UPC-E barcode */
1193 static int makeUpcE (struct state *st, Bitmap *dest, char *digits, int y)
1195 char expandedDigits[13];
1196 char compressedDigits[9];
1198 expandedDigits[0] = '\0';
1199 compressedDigits[0] = '0';
1200 strcpy (compressedDigits + 1, digits);
1202 expandToUpcADigits (compressedDigits, expandedDigits);
1203 if (expandedDigits[0] == '\0')
1208 compressedDigits[7] = expandedDigits[11];
1210 return makeUpcEFull (st, dest, compressedDigits, y);
1213 /* draw the actual barcode part of a EAN-13 barcode */
1214 static void drawEan13Bars (Bitmap *upcBitmap, char *digits, int x, int y,
1215 int barY2, int guardY2)
1218 int leftPattern = ean13FirstDigit[charToDigit (digits[0])];
1221 bitmapVlin (upcBitmap, x, y, guardY2);
1222 bitmapVlin (upcBitmap, x + 2, y, guardY2);
1225 bitmapVlin (upcBitmap, x + 46, y, guardY2);
1226 bitmapVlin (upcBitmap, x + 48, y, guardY2);
1229 bitmapVlin (upcBitmap, x + 92, y, guardY2);
1230 bitmapVlin (upcBitmap, x + 94, y, guardY2);
1232 for (i = 0; i < 6; i++)
1234 UpcSet lset = (leftPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
1236 drawUpcEanDigit (upcBitmap,
1242 drawUpcEanDigit (upcBitmap,
1251 /* make and return a full-height EAN-13 barcode */
1252 static int makeEan13Full (struct state *st, Bitmap *dest, char *digits, int y)
1254 int baseWidth = 102;
1255 int baseHeight = 60;
1257 int height = baseHeight + y;
1261 drawEan13Bars (dest, digits, 6, y, height - 10, height - 4);
1263 drawDigitChar (st, dest, 0, height - 7, digits[0]);
1265 for (i = 0; i < 6; i++)
1267 drawDigitChar (st, dest, 11 + i*7, height - 7, digits[i+1]);
1268 drawDigitChar (st, dest, 57 + i*7, height - 7, digits[i+7]);
1274 /* make and return an EAN-13 barcode */
1275 static int makeEan13 (struct state *st, Bitmap *dest, char *digits, int y)
1278 unsigned int mul = 1;
1279 unsigned int sum = 0;
1281 for (i = 0; i < 12; i++)
1283 sum += charToDigit (digits[i]) * mul;
1287 if (digits[12] == '?')
1289 digits[12] = ((10 - (sum % 10)) % 10) + '0';
1292 return makeEan13Full (st, dest, digits, y);
1295 /* draw the actual barcode part of an EAN-8 barcode */
1296 static void drawEan8Bars (Bitmap *upcBitmap, char *digits, int x, int y,
1297 int barY2, int guardY2)
1302 bitmapVlin (upcBitmap, x, y, guardY2);
1303 bitmapVlin (upcBitmap, x + 2, y, guardY2);
1306 bitmapVlin (upcBitmap, x + 32, y, guardY2);
1307 bitmapVlin (upcBitmap, x + 34, y, guardY2);
1310 bitmapVlin (upcBitmap, x + 64, y, guardY2);
1311 bitmapVlin (upcBitmap, x + 66, y, guardY2);
1313 for (i = 0; i < 4; i++)
1315 drawUpcEanDigit (upcBitmap,
1321 drawUpcEanDigit (upcBitmap,
1330 /* make and return a full-height EAN-8 barcode */
1331 static int makeEan8Full (struct state *st, Bitmap *dest, char *digits, int y)
1334 int baseHeight = 60;
1336 int height = baseHeight + y;
1340 drawEan8Bars (dest, digits, 0, y, height - 10, height - 4);
1342 for (i = 0; i < 4; i++)
1344 drawDigitChar (st, dest, 5 + i*7, height - 7, digits[i]);
1345 drawDigitChar (st, dest, 37 + i*7, height - 7, digits[i+4]);
1351 /* make and return an EAN-8 barcode */
1352 static int makeEan8 (struct state *st, Bitmap *dest, char *digits, int y)
1355 unsigned int mul = 3;
1356 unsigned int sum = 0;
1358 for (i = 0; i < 7; i++)
1360 sum += charToDigit (digits[i]) * mul;
1364 if (digits[7] == '?')
1366 digits[7] = ((10 - (sum % 10)) % 10) + '0';
1369 return makeEan8Full (st, dest, digits, y);
1372 /* Dispatch to the right form factor UPC/EAN barcode generator */
1373 static void processUpcEan (struct state *st, char *str, Bitmap *dest)
1378 int supDigitCount = 0;
1380 char *banner = NULL;
1385 while ((digitCount < 15) && (supDigitCount < 7))
1388 if (((c >= '0') && (c <= '9')) || (c == '?'))
1392 supDigits[supDigitCount] = *instr;
1397 digits[digitCount] = *instr;
1417 digits[digitCount] = '\0';
1418 supDigits[supDigitCount] = '\0';
1420 if (supDigitCount == 0)
1424 else if ((supDigitCount == 2) || (supDigitCount == 5))
1426 supplement = upcEanSupplementWidth (supDigits);
1430 fprintf (stderr, "%s: invalid supplement (must be 2 or 5 digits)\n",
1444 width = makeUpcE (st, dest, digits, vstart);
1449 width = makeEan8 (st, dest, digits, vstart);
1454 width = makeUpcA (st, dest, digits, vstart);
1459 width = makeEan13 (st, dest, digits, vstart);
1464 fprintf (stderr, "%s: bad barcode (%d digits)\n",
1465 progname, digitCount);
1472 drawUpcEanSupplementalBars (st, dest, supDigits,
1474 vstart + 1, dest->height - 4, 1);
1479 bitmapDrawString5x8 (dest,
1480 (width + supplement -
1481 ((int) strlen (banner) * 5)) / 2,
1489 /* ----------------------------------------------------------------------------
1494 * overall setup stuff
1497 /* set up the system */
1498 static void setup (struct state *st)
1500 XWindowAttributes xgwa;
1503 XGetWindowAttributes (st->dpy, st->window, &xgwa);
1505 st->visual = xgwa.visual;
1506 st->cmap = xgwa.colormap;
1507 st->windowWidth = xgwa.width;
1508 st->windowHeight = xgwa.height;
1510 gcv.background = get_pixel_resource (st->dpy, xgwa.colormap,
1511 "background", "Background");
1512 gcv.foreground = get_pixel_resource (st->dpy, xgwa.colormap,
1513 "foreground", "Foreground");
1514 st->fg_pixel = gcv.foreground;
1515 st->theGC = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv);
1517 st->theBitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG, BARCODE_HEIGHT * MAX_MAG);
1518 st->theImage = XCreateImage(st->dpy, st->visual, 1, XYBitmap, 0, st->theBitmap->buf,
1519 st->theBitmap->width, st->theBitmap->height, 8,
1520 st->theBitmap->widthBytes);
1521 st->theImage->bitmap_bit_order = LSBFirst;
1522 st->theImage->byte_order = LSBFirst;
1531 /* set up the model */
1532 static void setupModel (struct state *st)
1536 st->barcode_max = 20;
1537 st->barcode_count = 0;
1538 st->barcodes = malloc (sizeof (Barcode) * st->barcode_max);
1540 for (i = 0; i < st->barcode_max; i++)
1542 st->barcodes[i].bitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG,
1543 BARCODE_HEIGHT * MAX_MAG);
1547 /* make a new barcode string */
1548 static void makeBarcodeString (struct state *st, char *str)
1552 switch ((int) (RAND_FLOAT_01 * 4))
1554 case 0: dig = 6; break;
1555 case 1: dig = 7; break;
1556 case 2: dig = 11; break;
1557 default: dig = 12; break;
1560 for (i = 0; i < dig; i++)
1562 str[i] = RAND_FLOAT_01 * 10 + '0';
1568 switch ((int) (RAND_FLOAT_01 * 3))
1570 case 0: dig = 0; break;
1571 case 1: dig = 2; break;
1572 default: dig = 5; break;
1581 str[i] = RAND_FLOAT_01 * 10 + '0';
1590 strcpy(&str[i], words[(int) (RAND_FLOAT_01 * WORD_COUNT)]);
1593 /* update the model for one iteration */
1594 static void scrollModel (struct state *st)
1598 for (i = 0; i < st->barcode_count; i++)
1600 Barcode *b = &st->barcodes[i];
1602 if ((b->x + BARCODE_WIDTH * b->mag) < 0)
1604 /* fell off the edge */
1605 if (i != (st->barcode_count - 1)) {
1606 Bitmap *oldb = b->bitmap;
1607 memmove (b, b + 1, (st->barcode_count - i - 1) * sizeof (Barcode));
1608 st->barcodes[st->barcode_count - 1].bitmap = oldb;
1610 XFreeColors (st->dpy, st->cmap, &b->pixel, 1, 0);
1614 st->barcode_count--;
1618 while (st->barcode_count < st->barcode_max)
1620 Barcode *barcode = &st->barcodes[st->barcode_count];
1621 barcode->x = (st->barcode_count == 0) ?
1623 (st->barcodes[st->barcode_count - 1].x +
1624 st->barcodes[st->barcode_count - 1].mag * BARCODE_WIDTH);
1625 barcode->x += RAND_FLOAT_01 * 100;
1626 barcode->mag = RAND_FLOAT_01 * MAX_MAG;
1628 RAND_FLOAT_01 * (st->windowHeight - BARCODE_HEIGHT * barcode->mag);
1633 makeBarcodeString(st, barcode->code);
1634 processUpcEan (st, barcode->code, st->theBitmap);
1635 bitmapScale (barcode->bitmap, st->theBitmap, barcode->mag);
1640 for (ii = 0; ii < 100; ii++)
1642 hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1643 ok = XAllocColor (st->dpy, st->cmap, &c);
1648 c.red = c.green = c.blue = 0xFFFF;
1649 if (!XAllocColor (st->dpy, st->cmap, &c))
1652 barcode->pixel = c.pixel;
1655 st->barcode_count++;
1659 /* update the model for one iteration */
1660 static void updateGrid (struct state *st)
1664 if (st->grid_w == 0 || st->grid_h == 0 ||
1665 (! (random() % 400)))
1667 XClearWindow (st->dpy, st->window);
1668 st->grid_w = 1 + (random() % 3);
1669 st->grid_h = 1 + (random() % 4);
1672 if (!st->grid_alloced_p || (! (random() % 100)))
1675 hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1676 if (st->grid_alloced_p)
1677 XFreeColors (st->dpy, st->cmap, &st->grid_pixel, 1, 0);
1678 XAllocColor (st->dpy, st->cmap, &c);
1679 st->grid_pixel = c.pixel;
1680 st->grid_alloced_p = 1;
1683 st->barcode_count = st->grid_w * st->grid_h;
1684 if (st->barcode_count > st->barcode_max) abort();
1686 for (i = 0; i < st->barcode_max; i++)
1688 Barcode *b = &st->barcodes[i];
1689 b->x = b->y = 999999;
1693 for (y = 0; y < st->grid_h; y++)
1694 for (x = 0; x < st->grid_w; x++, i++)
1696 Barcode *b = &st->barcodes[i];
1699 int cell_w = (st->windowWidth / st->grid_w);
1700 int cell_h = (st->windowHeight / st->grid_h);
1701 int mag_x = cell_w / BARCODE_WIDTH;
1702 int mag_y = cell_h / BARCODE_HEIGHT;
1703 int BW = 108 /*BARCODE_WIDTH*/;
1704 int BH = BARCODE_HEIGHT;
1706 b->mag = (mag_x < mag_y ? mag_x : mag_y);
1708 b->x = (x * cell_w) + ((cell_w - b->mag * BW) / 2);
1709 b->y = (y * cell_h) + ((cell_h - b->mag * BH) / 2);
1710 b->pixel = st->grid_pixel;
1712 if (!st->strings[i])
1715 char *s = malloc (digits + 10);
1717 for (j = 0; j < digits; j++)
1718 s[j] = (random() % 10) + '0';
1724 /* change one digit in this barcode */
1725 st->strings[i][random() % digits] = (random() % 10) + '0';
1727 strcpy (b->code, st->strings[i]);
1728 processUpcEan (st, b->code, b->bitmap);
1733 /* update the model for one iteration.
1734 This one draws a clock. By jwz. */
1735 static void updateClock (struct state *st)
1737 Barcode *b = &st->barcodes[0];
1738 int BW = 76 /* BARCODE_WIDTH */;
1739 int BH = BARCODE_HEIGHT;
1742 time_t now = time ((time_t *) 0);
1743 struct tm *tm = localtime (&now);
1744 XWindowAttributes xgwa;
1745 int ow = st->windowWidth;
1746 int oh = st->windowHeight;
1748 XGetWindowAttributes (st->dpy, st->window, &xgwa);
1749 st->windowWidth = xgwa.width;
1750 st->windowHeight = xgwa.height;
1752 mag_x = st->windowWidth / BW;
1753 mag_y = st->windowHeight / BH;
1755 st->barcode_count = 1;
1757 b->mag = (mag_x < mag_y ? mag_x : mag_y);
1759 if (b->mag > MAX_MAG) b->mag = MAX_MAG;
1760 if (b->mag < 1) b->mag = 1;
1762 b->x = (st->windowWidth - (b->mag * BW )) / 2;
1763 b->y = (st->windowHeight - (b->mag * (BH + 9))) / 2;
1764 b->pixel = st->fg_pixel;
1766 if (!st->button_down_p)
1767 sprintf (b->code, "0%02d%02d%02d?:",
1768 (st->mode == BC_CLOCK24
1778 sprintf (b->code, "0%02d%02d%02d?:",
1779 tm->tm_year % 100, tm->tm_mon+1, tm->tm_mday);
1783 int hh = BH + vstart;
1784 char expandedDigits[13];
1786 expandedDigits[0] = '\0';
1788 expandToUpcADigits (b->code, expandedDigits);
1789 if (expandedDigits[0] != '\0')
1790 b->code[7] = expandedDigits[11];
1792 bitmapClear (st->theBitmap);
1793 drawUpcEBars (st, st->theBitmap, b->code, 6, 9, 59, 65);
1794 for (i = 0; i < 6; i++)
1796 int off = (i < 2 ? 0 :
1799 drawDigitChar (st, st->theBitmap, 11 + i*7 + off, hh - 16, b->code[i+1]);
1802 if (!st->button_down_p)
1805 char *days[] = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
1806 char *s = days[tm->tm_wday];
1807 bitmapDrawString5x8 (st->theBitmap, (BW - strlen (s)*5) / 2, 0, s);
1809 drawDigitChar (st, st->theBitmap, 0, hh - 23, (tm->tm_hour < 12 ? 'A' : 'P'));
1810 drawDigitChar (st, st->theBitmap, 68, hh - 23, 'M');
1815 sprintf (s, "%03d", tm->tm_yday);
1816 bitmapDrawString5x8 (st->theBitmap, (BW - strlen (s)*5) / 2, 0, s);
1820 bitmapScale (b->bitmap, st->theBitmap, b->mag);
1822 if (ow != st->windowWidth || oh != st->windowHeight)
1823 XClearWindow (st->dpy, st->window);
1828 /* render and dpy the current model */
1829 static void renderFrame (struct state *st)
1833 for (i = 0; i < st->barcode_count; i++)
1835 Barcode *barcode = &st->barcodes[i];
1837 if (barcode->x > st->windowWidth) {
1841 /* bitmapScale (st->theBitmap, barcode->bitmap, barcode->mag);*/
1842 st->theImage->data = barcode->bitmap->buf;
1844 XSetForeground (st->dpy, st->theGC, barcode->pixel);
1845 XPutImage (st->dpy, st->window, st->theGC, st->theImage,
1846 0, 0, barcode->x, barcode->y,
1847 BARCODE_WIDTH * barcode->mag,
1848 BARCODE_HEIGHT * barcode->mag);
1852 /* do one iteration */
1853 static unsigned long
1854 barcode_draw (Display *dpy, Window win, void *closure)
1856 struct state *st = (struct state *) closure;
1857 if (st->mode == BC_SCROLL)
1859 else if (st->mode == BC_GRID)
1861 else if (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24)
1873 barcode_event (Display *dpy, Window window, void *closure, XEvent *event)
1875 struct state *st = (struct state *) closure;
1876 int clockp = (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24);
1877 if (clockp && event->xany.type == ButtonPress) {
1878 st->button_down_p = True;
1880 } else if (clockp && event->xany.type == ButtonRelease) {
1881 st->button_down_p = False;
1888 barcode_reshape (Display *dpy, Window window, void *closure,
1889 unsigned int w, unsigned int h)
1894 barcode_free (Display *dpy, Window window, void *closure)
1899 /* main and options and stuff */
1901 static const char *barcode_defaults [] = {
1902 ".background: black",
1903 ".foreground: green",
1910 static XrmOptionDescRec barcode_options [] = {
1911 { "-delay", ".delay", XrmoptionSepArg, 0 },
1912 { "-mode", ".mode", XrmoptionSepArg, 0 },
1913 { "-scroll", ".mode", XrmoptionNoArg, "scroll" },
1914 { "-grid", ".mode", XrmoptionNoArg, "grid" },
1915 { "-clock", ".mode", XrmoptionNoArg, "clock" },
1916 { "-clock12", ".mode", XrmoptionNoArg, "clock12" },
1917 { "-clock24", ".mode", XrmoptionNoArg, "clock24" },
1921 /* initialize the user-specifiable params */
1922 static void initParams (struct state *st)
1927 st->delay = get_integer_resource (st->dpy, "delay", "Delay");
1930 fprintf (stderr, "%s: delay must be at least 0\n", progname);
1934 s = get_string_resource (st->dpy, "mode", "Mode");
1935 if (!s || !*s || !strcasecmp (s, "scroll"))
1936 st->mode = BC_SCROLL;
1937 else if (!strcasecmp (s, "grid"))
1939 else if (!strcasecmp (s, "clock") ||
1940 !strcasecmp (s, "clock12"))
1941 st->mode = BC_CLOCK12;
1942 else if (!strcasecmp (s, "clock24"))
1943 st->mode = BC_CLOCK24;
1946 fprintf (stderr, "%s: unknown mode \"%s\"\n", progname, s);
1951 if (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24)
1952 st->delay = 10000; /* only update every 1/10th second */
1961 barcode_init (Display *dpy, Window win)
1963 struct state *st = (struct state *) calloc (1, sizeof(*st));
1974 XSCREENSAVER_MODULE ("Barcode", barcode)