/* draw a upc/ean digit at the given coordinates */ static void drawUpcEanDigit (Bitmap *upcBitmap, int x, int y1, int y2, char n, UpcSet set) { unsigned int bits; int i; n = charToDigit (n); switch (set) { case UPC_LEFT_A: bits = upcLeftA[(int) n]; break; case UPC_LEFT_B: bits = upcLeftB[(int) n]; break; default /* case UPC_RIGHT */: bits = upcRight[(int) n]; break; } for (i = 6; i >=0; i--) { if (bits & (1 << i)) { bitmapVlin (upcBitmap, x, y1, y2); } x++; } }
long a64l(const char* s) { unsigned long ret = 0; for (int i = 0; i < 6; i++) { int digit = charToDigit(s[i]); if (digit == -1) { break; } ret |= digit << (6 * i); } return ret & 0xFFFFFFFF; }
/* draw the actual barcode part of a UPC-E barcode */ static void drawUpcEBars (struct state *st, Bitmap *upcBitmap, char *digits, int x, int y, int barY2, int guardY2) { int i; int parityPattern = upcELastDigit[charToDigit(digits[7])]; int clockp = (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24); if (digits[0] == '1') { parityPattern = ~parityPattern; } /* header */ bitmapVlin (upcBitmap, x, y, guardY2); bitmapVlin (upcBitmap, x + 2, y, guardY2); /* trailer */ bitmapVlin (upcBitmap, x + 46 + (clockp?8:0), y, guardY2); bitmapVlin (upcBitmap, x + 48 + (clockp?8:0), y, guardY2); bitmapVlin (upcBitmap, x + 50 + (clockp?8:0), y, guardY2); /* clock kludge -- this draws an extra set of dividers after digits 2 and 4. This makes this *not* be a valid bar code, but, it looks pretty for the clock dpy. */ if (clockp) { bitmapVlin (upcBitmap, x + 18, y, guardY2); bitmapVlin (upcBitmap, x + 18 + 2, y, guardY2); bitmapVlin (upcBitmap, x + 36, y, guardY2); bitmapVlin (upcBitmap, x + 36 + 2, y, guardY2); } for (i = 0; i < 6; i++) { UpcSet lset = (parityPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A; int off = (clockp ? (i < 2 ? 0 : i < 4 ? 4 : /* extra spacing for clock bars */ 8) : 0); drawUpcEanDigit (upcBitmap, x + 3 + i*7 + off, y, barY2, digits[i + 1], lset); } }
/* make and return an EAN-8 barcode */ static int makeEan8 (struct state *st, Bitmap *dest, char *digits, int y) { int i; unsigned int mul = 3; unsigned int sum = 0; for (i = 0; i < 7; i++) { sum += charToDigit (digits[i]) * mul; mul ^= 2; } if (digits[7] == '?') { digits[7] = ((10 - (sum % 10)) % 10) + '0'; } return makeEan8Full (st, dest, digits, y); }
/* draw the actual barcode part of a EAN-13 barcode */ static void drawEan13Bars (Bitmap *upcBitmap, char *digits, int x, int y, int barY2, int guardY2) { int i; int leftPattern = ean13FirstDigit[charToDigit (digits[0])]; /* header */ bitmapVlin (upcBitmap, x, y, guardY2); bitmapVlin (upcBitmap, x + 2, y, guardY2); /* center marker */ bitmapVlin (upcBitmap, x + 46, y, guardY2); bitmapVlin (upcBitmap, x + 48, y, guardY2); /* trailer */ bitmapVlin (upcBitmap, x + 92, y, guardY2); bitmapVlin (upcBitmap, x + 94, y, guardY2); for (i = 0; i < 6; i++) { UpcSet lset = (leftPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A; drawUpcEanDigit (upcBitmap, x + 3 + i*7, y, barY2, digits[i+1], lset); drawUpcEanDigit (upcBitmap, x + 50 + i*7, y, barY2, digits[i+7], UPC_RIGHT); } }
/* draw the given supplemental barcode, including the textual digits */ static void drawUpcEanSupplementalBars (struct state *st, Bitmap *upcBitmap, char *digits, int x, int y, int y2, int textAbove) { int len = strlen (digits); int i; int parity; int textY; int textX; if (textAbove) { textY = y; y += 8; } else { y2 -= 8; textY = y2 + 2; } x += 8; /* skip the space between the main and supplemental */ switch (len) { case 2: { textX = x + 5; parity = (charToDigit (digits[0]) * 10 + charToDigit (digits[1])) & 0x3; break; } case 5: { textX = x + 10; parity = ((charToDigit (digits[0]) + charToDigit (digits[2]) + charToDigit (digits[4])) * 3 + (charToDigit (digits[1]) + charToDigit (digits[3])) * 9) % 10; parity = upcELastDigit[parity]; break; } default: { fprintf (stderr, "%s: bad supplement (%d digits)\n", progname, len); exit(1); break; } } /* header */ bitmapVlin (upcBitmap, x, y, y2); bitmapVlin (upcBitmap, x + 2, y, y2); bitmapVlin (upcBitmap, x + 3, y, y2); for (i = 0; i < len; i++) { UpcSet lset = (parity & (1 << (len - 1 - i))) ? UPC_LEFT_B : UPC_LEFT_A; int baseX = x + 2 + i * 9; /* separator / end of header */ if (i == 0) { bitmapVlin (upcBitmap, baseX, y, y2); } bitmapVlin (upcBitmap, baseX + 1, y, y2); drawUpcEanDigit (upcBitmap, baseX + 2, y, y2, digits[i], lset); drawDigitChar (st, upcBitmap, textX + i*6, textY, digits[i]); } }
/* expand 8 UPC-E digits into a UPC-A number, storing into the given result * array, or just store '\0' into the first element, if the form factor * is incorrect; this will also calculate the check digit, if it is * specified as '?' */ static void expandToUpcADigits (char *compressed, char *expanded) { int i; if ((compressed[0] != '0') && (compressed[0] != '1')) { return; } expanded[0] = compressed[0]; expanded[6] = '0'; expanded[7] = '0'; expanded[11] = compressed[7]; switch (compressed[6]) { case '0': case '1': case '2': { expanded[1] = compressed[1]; expanded[2] = compressed[2]; expanded[3] = compressed[6]; expanded[4] = '0'; expanded[5] = '0'; expanded[8] = compressed[3]; expanded[9] = compressed[4]; expanded[10] = compressed[5]; break; } case '3': { expanded[1] = compressed[1]; expanded[2] = compressed[2]; expanded[3] = compressed[3]; expanded[4] = '0'; expanded[5] = '0'; expanded[8] = '0'; expanded[9] = compressed[4]; expanded[10] = compressed[5]; break; } case '4': { expanded[1] = compressed[1]; expanded[2] = compressed[2]; expanded[3] = compressed[3]; expanded[4] = compressed[4]; expanded[5] = '0'; expanded[8] = '0'; expanded[9] = '0'; expanded[10] = compressed[5]; break; } default: { expanded[1] = compressed[1]; expanded[2] = compressed[2]; expanded[3] = compressed[3]; expanded[4] = compressed[4]; expanded[5] = compressed[5]; expanded[8] = '0'; expanded[9] = '0'; expanded[10] = compressed[6]; break; } } if (expanded[11] == '?') { unsigned int mul = 3; unsigned int sum = 0; for (i = 0; i < 11; i++) { sum += charToDigit (expanded[i]) * mul; mul ^= 2; } expanded[11] = ((10 - (sum % 10)) % 10) + '0'; } }