Adds a jsPDF method to draw a Code 39 barcode in line vector, which is very small and retain perfect sharpness at all resolutions. An optional matrix can be supplied for rotation, sheer, mirror, or other effects.
Does not render text; the drawn barcode is perfectly rectangular. Does not validate text input. Requires EcmaScript 7.
const doc = new jsPDF();
// Draw at [50,50], width 100. height 20.
doc.code39( "0123456789", 50, 30, 100, 20 );
// Thin lines (scale 2, or use 3 for thick lines).
doc.code39( "0123456789", 55, 60, 90, 20, 2 );
// Rotate clockwise 90' + transpose to [145,90].
doc.code39( "0123456789", 0, 0, 90, 20, 2, [0,-1,145,1,0,90] );
// Anti-clockwise 90' + transpose to [55,180].
doc.code39( "0123456789", 0, 0, 90, 20, 2, [0,1,55,-1,0,180] );
// Sheer + transpose to [50,190]
doc.code39( "0123456789", 0, 0, 90, 20, 2.5, [1,0.3,50,0,1,190] );
doc.save( "test.pdf" );
document.addEventListener( 'DOMContentLoaded', function(){
// https://gist.github.com/Sheep-y/baaebc7b9a465dec09d0014520b81933/
Object.getPrototypeOf( jsPDF.prototype ).code39 = function drawCode39 ( text, x, y, w, h, scale = 2.5, matrix = null ) {
if ( x === undefined || y === undefined || w <= 0 || h <= 0 ) return;
scale = Math.max( 2, Math.min( +scale, 3 ) );
const Code39Chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%";
const Code39Bars =
[ "000110100","100100001","001100001","101100000","000110001","100110000","001110000","000100101","100100100", //0-8
"001100100","100001001","001001001","101001000","000011001","100011000","001011000","000001101","100001100", //9-H
"001001100","000011100","100000011","001000011","101000010","000010011","100010010","001010010","000000111", //I-Q
"100000110","001000110","000010110","110000001","011000001","111000000","010010001","110010000","011010000", //R-Z
"010000101","110000100","011000100","010010100","010101000","010100010","010001010","000101010" ]; // Symbols
text = `*${text}*`.toUpperCase();
const charCount = text.length, charWidth = w / charCount, lineWidth = charWidth / ( 7 + scale * 3 );
//console.log( `Code 39 "${text}" at [${x},${y}] height ${h} width ${w} (${charWidth} per char, ${lineWidth} per line}). Matrix ${matrix}.` );
const spacing = [ lineWidth, scale * lineWidth ], d = lineWidth*(scale-1)/2;
this.setLineCap( 2 ); // square cap
for ( let i = 0, draw = true ; i < charCount ; i++, draw = true ) {
let pos = Code39Chars.indexOf( text[i] ), left = x + charWidth * i;
for ( let w of Code39Bars[pos].split( "" ).map( e => +e ) ) {
if ( draw ) {
this.setLineWidth( spacing[ w ] );
let dw = w?d:0, x1 = left+dw, y1 = y+dw, x2 = left+dw, y2 = y+h-dw;
if ( matrix ) {
[ x1, y1 ] = applyMatrix( x1, y1 );
[ x2, y2 ] = applyMatrix( x2, y2 );
}
this.line( x1, y1, x2, y2 );
}
left += spacing[ w ];
draw = ! draw;
}
}
function applyMatrix( x, y ) {
return [ x * matrix[0] + y * matrix[1] + matrix[2], x * matrix[3] + y * matrix[4] + matrix[5] ];
}
};
} );
This code is released to the public domain. Do whatever you like.