123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- /*
- * barcode generator - UPC-E
- */
- var Barcode1D = require('./utils/draw1D'),
- getCheckDigit = require('./utils/checksums').weight3odd10;
- // BARMAP[parity][digit]
- const BARMAP = [
- [
- [1,1,2,3], [1,2,2,2], [2,2,1,2], [1,1,4,1], [2,3,1,1],
- [1,3,2,1], [4,1,1,1], [2,1,3,1], [3,1,2,1], [2,1,1,3]
- ],
- [
- [3,2,1,1], [2,2,2,1], [2,1,2,2], [1,4,1,1], [1,1,3,2],
- [1,2,3,1], [1,1,1,4], [1,3,1,2], [1,2,1,3], [3,1,1,2]
- ]
- ];
- // PAIRITYMAP[check][lead]
- const PAIRITYMAP = [
- [ [0,0,0,1,1,1],[1,1,1,0,0,0] ],
- [ [0,0,1,0,1,1],[1,1,0,1,0,0] ],
- [ [0,0,1,1,0,1],[1,1,0,0,1,0] ],
- [ [0,0,1,1,1,0],[1,1,0,0,0,1] ],
- [ [0,1,0,0,1,1],[1,0,1,1,0,0] ],
- [ [0,1,1,0,0,1],[1,0,0,1,1,0] ],
- [ [0,1,1,1,0,0],[1,0,0,0,1,1] ],
- [ [0,1,0,1,0,1],[1,0,1,0,1,0] ],
- [ [0,1,0,1,1,0],[1,0,1,0,0,1] ],
- [ [0,1,1,0,1,0],[1,0,0,1,0,1] ]
- ];
- const START = [1,1,1];
- const END = [1,1,1,1,1,1]
- /*
- * This will be the same with all UPC-Es
- * 3 Start
- * 42 Data (6x7)
- * + 6 End
- * ---------------
- * 51 Fixed width
- */
- const MODULE_WIDTH = 51;
- /*
- * Get a valid UPC-E pattern from UPC-A
- * NOTE: This gets the pattern only! It does not provide you with parity data
- * nor does it provide you with check digits, it ignores all that in the input
- *
- * @param String - UPC-A String
- * @return String - UPC-E code pattern. Empty string if invalid
- */
- function fromUpcA(upcastr) {
- var upca = upcastr.split('');
- if (upca.length == 12) {
- upca.pop();
- }
- var first = upca.shift();
- if (upca.length != 10 || first != 1 && first != 0) {
- return '';
- }
- var upcamask = upca.join(''),
- match = null,
- upce = '';
- // case 0-2
- if (match = upcamask.match(/^([0-9]{2})([0-2])0{4}([0-9]{3})$/ )) {
- upce = match[1] + match[3] + match[2];
- }
- // case 3
- else if (match = upcamask.match(/^([0-9]{3})0{5}([0-9]{2})$/)) {
- upce = match[1] + match[2] + '3';
- }
- // case 4
- else if (match = upcamask.match(/^([0-9]{4})0{5}([0-9])$/)) {
- upce = match[1] + match[2] + '4';
- }
- // case 5-9
- else if (match = upcamask.match(/^([0-9]{5})0{4}([5-9])$/)) {
- upce = match[1] + match[2];
- }
- return upce;
- }
- /*
- * generate sequence
- * @param String pattern
- * @param Number parity
- * @param Number check
- */
- function generateSequence(pattern, parity, check) {
- if (pattern.length !== 6) {
- return null;
- }
- check = parseInt(check);
- parity = parseInt(parity);
- var p = PAIRITYMAP[check][parity],
- seq = START;
- for (var i = 0; i < 6; i++) {
- seq = seq.concat( BARMAP[ p[i] ][ parseInt(pattern[i]) ] );
- }
- return seq.concat(END);
- }
- function createCode(options, callback) {
- if (!options.w || !options.h) {
- return callback(new Error('Width and Height must be non-zero'), {});
- }
- var barWidth = options.w / MODULE_WIDTH >> 0;
- if (!barWidth) {
- return callback(new Error('Width will result in a degenerate barcode'), {});
- }
- var pattern = fromUpcA(options.data),
- parity = parseInt(options.data.substr(0,1));
- var check = getCheckDigit(options.data.substr(0,11));
- if (!pattern || parity > 1) {
- return callback(new Error('UPC-E Requires a valid UPC-A code starting with 0 or 1'), {});
- }
- // NOTE: Sequence is just one long array, not an array of arrays.
- var seq = generateSequence(pattern, parity, check);
- new Barcode1D().setWidth(options.w)
- .setHeight(options.h)
- .setModuleWidth(MODULE_WIDTH)
- .draw(seq, callback);
- }
- module.exports.generateSequence = generateSequence;
- module.exports.createCode = createCode;
- module.exports.fromUpcA = fromUpcA;
|