2020-12-19 17:39:48 +01:00
// Code39 barcode generator
// see https://en.wikipedia.org/wiki/Code_39
// IBM LTO Ultrium Cartridge Label Specification
// http://www-01.ibm.com/support/docview.wss?uid=ssg1S7000429
2021-02-28 19:35:43 +01:00
const code39 _codes = {
2020-12-19 17:39:48 +01:00
"1" : [ 'B' , 's' , 'b' , 'S' , 'b' , 's' , 'b' , 's' , 'B' ] ,
"A" : [ 'B' , 's' , 'b' , 's' , 'b' , 'S' , 'b' , 's' , 'B' ] ,
"K" : [ 'B' , 's' , 'b' , 's' , 'b' , 's' , 'b' , 'S' , 'B' ] ,
"U" : [ 'B' , 'S' , 'b' , 's' , 'b' , 's' , 'b' , 's' , 'B' ] ,
"2" : [ 'b' , 's' , 'B' , 'S' , 'b' , 's' , 'b' , 's' , 'B' ] ,
"B" : [ 'b' , 's' , 'B' , 's' , 'b' , 'S' , 'b' , 's' , 'B' ] ,
"L" : [ 'b' , 's' , 'B' , 's' , 'b' , 's' , 'b' , 'S' , 'B' ] ,
"V" : [ 'b' , 'S' , 'B' , 's' , 'b' , 's' , 'b' , 's' , 'B' ] ,
"3" : [ 'B' , 's' , 'B' , 'S' , 'b' , 's' , 'b' , 's' , 'b' ] ,
"C" : [ 'B' , 's' , 'B' , 's' , 'b' , 'S' , 'b' , 's' , 'b' ] ,
"M" : [ 'B' , 's' , 'B' , 's' , 'b' , 's' , 'b' , 'S' , 'b' ] ,
"W" : [ 'B' , 'S' , 'B' , 's' , 'b' , 's' , 'b' , 's' , 'b' ] ,
"4" : [ 'b' , 's' , 'b' , 'S' , 'B' , 's' , 'b' , 's' , 'B' ] ,
"D" : [ 'b' , 's' , 'b' , 's' , 'B' , 'S' , 'b' , 's' , 'B' ] ,
"N" : [ 'b' , 's' , 'b' , 's' , 'B' , 's' , 'b' , 'S' , 'B' ] ,
"X" : [ 'b' , 'S' , 'b' , 's' , 'B' , 's' , 'b' , 's' , 'B' ] ,
"5" : [ 'B' , 's' , 'b' , 'S' , 'B' , 's' , 'b' , 's' , 'b' ] ,
"E" : [ 'B' , 's' , 'b' , 's' , 'B' , 'S' , 'b' , 's' , 'b' ] ,
"O" : [ 'B' , 's' , 'b' , 's' , 'B' , 's' , 'b' , 'S' , 'b' ] ,
"Y" : [ 'B' , 'S' , 'b' , 's' , 'B' , 's' , 'b' , 's' , 'b' ] ,
"6" : [ 'b' , 's' , 'B' , 'S' , 'B' , 's' , 'b' , 's' , 'b' ] ,
"F" : [ 'b' , 's' , 'B' , 's' , 'B' , 'S' , 'b' , 's' , 'b' ] ,
"P" : [ 'b' , 's' , 'B' , 's' , 'B' , 's' , 'b' , 'S' , 'b' ] ,
"Z" : [ 'b' , 'S' , 'B' , 's' , 'B' , 's' , 'b' , 's' , 'b' ] ,
"7" : [ 'b' , 's' , 'b' , 'S' , 'b' , 's' , 'B' , 's' , 'B' ] ,
"G" : [ 'b' , 's' , 'b' , 's' , 'b' , 'S' , 'B' , 's' , 'B' ] ,
"Q" : [ 'b' , 's' , 'b' , 's' , 'b' , 's' , 'B' , 'S' , 'B' ] ,
"-" : [ 'b' , 'S' , 'b' , 's' , 'b' , 's' , 'B' , 's' , 'B' ] ,
"8" : [ 'B' , 's' , 'b' , 'S' , 'b' , 's' , 'B' , 's' , 'b' ] ,
"H" : [ 'B' , 's' , 'b' , 's' , 'b' , 'S' , 'B' , 's' , 'b' ] ,
"R" : [ 'B' , 's' , 'b' , 's' , 'b' , 's' , 'B' , 'S' , 'b' ] ,
"." : [ 'B' , 'S' , 'b' , 's' , 'b' , 's' , 'B' , 's' , 'b' ] ,
"9" : [ 'b' , 's' , 'B' , 'S' , 'b' , 's' , 'B' , 's' , 'b' ] ,
"I" : [ 'b' , 's' , 'B' , 's' , 'b' , 'S' , 'B' , 's' , 'b' ] ,
"S" : [ 'b' , 's' , 'B' , 's' , 'b' , 's' , 'B' , 'S' , 'b' ] ,
" " : [ 'b' , 'S' , 'B' , 's' , 'b' , 's' , 'B' , 's' , 'b' ] ,
"0" : [ 'b' , 's' , 'b' , 'S' , 'B' , 's' , 'B' , 's' , 'b' ] ,
"J" : [ 'b' , 's' , 'b' , 's' , 'B' , 'S' , 'B' , 's' , 'b' ] ,
"T" : [ 'b' , 's' , 'b' , 's' , 'B' , 's' , 'B' , 'S' , 'b' ] ,
2021-02-12 13:49:38 +01:00
"*" : [ 'b' , 'S' , 'b' , 's' , 'B' , 's' , 'B' , 's' , 'b' ] ,
2020-12-19 17:39:48 +01:00
} ;
2021-02-28 19:35:43 +01:00
const colors = [
2020-12-19 17:39:48 +01:00
'#BB282E' ,
'#FAE54A' ,
'#9AC653' ,
'#01A5E2' ,
'#9EAAB6' ,
'#D97E35' ,
'#E27B99' ,
'#67A945' ,
'#F6B855' ,
2021-02-12 13:49:38 +01:00
'#705A81' ,
2020-12-19 17:39:48 +01:00
] ;
2021-02-28 19:31:35 +01:00
const lto _label _width = 70 ;
const lto _label _height = 16.9 ;
2020-12-19 17:39:48 +01:00
function foreach _label ( page _layout , callback ) {
let count = 0 ;
let row = 0 ;
let height = page _layout . margin _top ;
while ( ( height + page _layout . label _height ) <= page _layout . page _height ) {
let column = 0 ;
let width = page _layout . margin _left ;
while ( ( width + page _layout . label _width ) <= page _layout . page _width ) {
callback ( column , row , count , width , height ) ;
count += 1 ;
column += 1 ;
width += page _layout . label _width ;
width += page _layout . column _spacing ;
}
row += 1 ;
height += page _layout . label _height ;
height += page _layout . row _spacing ;
}
}
function compute _max _labels ( page _layout ) {
let max _labels = 0 ;
foreach _label ( page _layout , function ( ) { max _labels += 1 ; } ) ;
return max _labels ;
}
function svg _label ( mode , label , label _type , pagex , pagey , label _borders ) {
let svg = "" ;
2021-02-28 19:35:43 +01:00
if ( label . length !== 6 ) {
2020-12-19 17:39:48 +01:00
throw "wrong label length" ;
}
2021-02-28 19:35:43 +01:00
if ( label _type . length !== 2 ) {
2020-12-19 17:39:48 +01:00
throw "wrong label_type length" ;
}
let ratio = 2.75 ;
let parts = 3 * ratio + 6 ; // 3*wide + 6*small;
let barcode _width = ( lto _label _width / 12 ) * 10 ; // 10*code + 2margin
let small = barcode _width / ( parts * 10 + 9 ) ;
let code _width = small * parts ;
let wide = small * ratio ;
let xpos = pagex + code _width ;
let height = 12 ;
2021-02-28 19:35:43 +01:00
let label _rect = ` x=' ${ pagex } ' y=' ${ pagey } ' width=' ${ lto _label _width } ' height=' ${ lto _label _height } ' ` ;
2020-12-19 17:39:48 +01:00
if ( mode === 'placeholder' ) {
if ( label _borders ) {
2021-02-28 19:35:43 +01:00
svg += ` <rect class='unprintable' ${ label _rect } fill='none' style='stroke:black;stroke-width:0.1;'/> ` ;
2020-12-19 17:39:48 +01:00
}
return svg ;
}
if ( label _borders ) {
2021-02-28 19:35:43 +01:00
svg += ` <rect ${ label _rect } fill='none' style='stroke:black;stroke-width:0.1;'/> ` ;
2020-12-19 17:39:48 +01:00
}
2021-02-28 19:35:43 +01:00
if ( mode === "color" || mode === "frame" ) {
2020-12-19 17:39:48 +01:00
let w = lto _label _width / 8 ;
let h = lto _label _height - height ;
2021-02-28 19:35:43 +01:00
for ( let i = 0 ; i < 7 ; i ++ ) {
2020-12-19 17:39:48 +01:00
let textx = w / 2 + pagex + i * w ;
let texty = pagey ;
let fill = "none" ;
if ( mode === "color" && ( i < 6 ) ) {
let letter = label . charAt ( i ) ;
if ( letter >= '0' && letter <= '9' ) {
fill = colors [ parseInt ( letter , 10 ) ] ;
}
}
svg += ` <rect x=' ${ textx } ' y=' ${ texty } ' width=' ${ w } ' height=' ${ h } ' style='stroke:black;stroke-width:0.2;fill: ${ fill } ;'/> ` ;
if ( i == 6 ) {
textx += 3 ;
texty += 3.7 ;
svg += ` <text x=' ${ textx } ' y=' ${ texty } ' style='font-weight:bold;font-size:3px;font-family:sans-serif;'> ${ label _type } </text> ` ;
} else {
let letter = label . charAt ( i ) ;
textx += 3.5 ;
texty += 4 ;
svg += ` <text x=' ${ textx } ' y=' ${ texty } ' style='font-weight:bold;font-size:4px;font-family:sans-serif;'> ${ letter } </text> ` ;
}
}
}
let raw _label = ` * ${ label } ${ label _type } * ` ;
2021-02-28 19:35:43 +01:00
for ( let i = 0 ; i < raw _label . length ; i ++ ) {
2020-12-19 17:39:48 +01:00
let letter = raw _label . charAt ( i ) ;
let code = code39 _codes [ letter ] ;
if ( code === undefined ) {
throw ` unable to encode letter ' ${ letter } ' with code39 ` ;
}
if ( mode === "simple" ) {
let textx = xpos + code _width / 2 ;
let texty = pagey + 4 ;
if ( i > 0 && ( i + 1 ) < raw _label . length ) {
svg += ` <text x=' ${ textx } ' y=' ${ texty } ' style='font-weight:bold;font-size:4px;font-family:sans-serif;'> ${ letter } </text> ` ;
}
}
for ( let c of code ) {
if ( c === 's' ) {
xpos += small ;
continue ;
}
if ( c === 'S' ) {
xpos += wide ;
continue ;
}
let w = c === 'B' ? wide : small ;
let ypos = pagey + lto _label _height - height ;
svg += ` <rect x=' ${ xpos } ' y=' ${ ypos } ' width=' ${ w } ' height=' ${ height } ' style='fill:black'/> ` ;
xpos = xpos + w ;
}
xpos += small ;
}
return svg ;
}
function html _page _header ( ) {
let html = "<html5>" ;
html += "<style>" ;
/* no page margins */
html += "@page{margin-left: 0px;margin-right: 0px;margin-top: 0px;margin-bottom: 0px;}" ;
/* to hide things on printed page */
2021-02-12 13:49:38 +01:00
html += "@media print { .unprintable { visibility: hidden; } }" ;
2020-12-19 17:39:48 +01:00
html += "</style>" ;
//html += "<body onload='window.print()'>";
html += "<body style='background-color: white;'>" ;
return html ;
}
function svg _page _header ( page _width , page _height ) {
let svg = "<svg version='1.1' xmlns='http://www.w3.org/2000/svg'" ;
svg += ` width=' ${ page _width } mm' height=' ${ page _height } mm' viewBox='0 0 ${ page _width } ${ page _height } '> ` ;
return svg ;
}
function printBarcodePage ( ) {
let frame = document . getElementById ( "print_frame" ) ;
let window = frame . contentWindow ;
window . print ( ) ;
}
function generate _barcode _page ( target _id , page _layout , label _list , calibration ) {
let svg = svg _page _header ( page _layout . page _width , page _layout . page _height ) ;
let c = calibration ;
console . log ( calibration ) ;
svg += "<g id='barcode_page'" ;
if ( c !== undefined ) {
svg += ` transform='scale( ${ c . scalex } , ${ c . scaley } ),translate( ${ c . offsetx } , ${ c . offsety } )' ` ;
}
svg += '>' ;
foreach _label ( page _layout , function ( column , row , count , xpos , ypos ) {
if ( count >= label _list . length ) { return ; }
let item = label _list [ count ] ;
svg += svg _label ( item . mode , item . label , item . tape _type , xpos , ypos , page _layout . label _borders ) ;
} ) ;
svg += "</g>" ;
svg += "</svg>" ;
let html = html _page _header ( ) ;
html += svg ;
html += "</body>" ;
html += "</html>" ;
let frame = document . getElementById ( target _id ) ;
setupPrintFrame ( frame , page _layout . page _width , page _layout . page _height ) ;
let fwindow = frame . contentWindow ;
fwindow . document . open ( ) ;
fwindow . document . write ( html ) ;
fwindow . document . close ( ) ;
}
function setupPrintFrame ( frame , page _width , page _height ) {
let dpi = 98 ;
let dpr = window . devicePixelRatio ;
if ( dpr !== undefined ) {
dpi = dpi * dpr ;
}
let ppmm = dpi / 25.4 ;
frame . width = page _width * ppmm ;
frame . height = page _height * ppmm ;
}
function generate _calibration _page ( target _id , page _layout , calibration ) {
let frame = document . getElementById ( target _id ) ;
setupPrintFrame ( frame , page _layout . page _width , page _layout . page _height ) ;
2021-02-12 13:49:38 +01:00
let svg = svg _page _header ( page _layout . page _width , page _layout . page _height ) ;
2020-12-19 17:39:48 +01:00
svg += "<defs>" ;
svg += "<marker id='endarrow' markerWidth='10' markerHeight='7' " ;
svg += "refX='10' refY='3.5' orient='auto'><polygon points='0 0, 10 3.5, 0 7' />" ;
svg += "</marker>" ;
svg += "<marker id='startarrow' markerWidth='10' markerHeight='7' " ;
svg += "refX='0' refY='3.5' orient='auto'><polygon points='10 0, 10 7, 0 3.5' />" ;
svg += "</marker>" ;
svg += "</defs>" ;
svg += "<rect x='50' y='50' width='100' height='100' style='fill:none;stroke-width:0.05;stroke:rgb(0,0,0)'/>" ;
let text _style = "style='font-weight:bold;font-size:4;font-family:sans-serif;'" ;
svg += ` <text x='10' y='99' ${ text _style } >Sx = 50mm</text> ` ;
svg += "<line x1='0' y1='100' x2='50' y2='100' stroke='#000' marker-end='url(#endarrow)' stroke-width='.25'/>" ;
svg += ` <text x='60' y='99' ${ text _style } >Dx = 100mm</text> ` ;
svg += "<line x1='50' y1='100' x2='150' y2='100' stroke='#000' marker-start='url(#startarrow)' marker-end='url(#endarrow)' stroke-width='.25'/>" ;
svg += ` <text x='142' y='10' ${ text _style } writing-mode='tb'>Sy = 50mm</text> ` ;
svg += "<line x1='140' y1='0' x2='140' y2='50' stroke='#000' marker-end='url(#endarrow)' stroke-width='.25'/>" ;
svg += ` <text x='142' y='60' ${ text _style } writing-mode='tb'>Dy = 100mm</text> ` ;
svg += "<line x1='140' y1='50' x2='140' y2='150' stroke='#000' marker-start='url(#startarrow)' marker-end='url(#endarrow)' stroke-width='.25'/>" ;
let c = calibration ;
if ( c !== undefined ) {
svg += ` <rect x='50' y='50' width='100' height='100' style='fill:none;stroke-width:0.05;stroke:rgb(255,0,0)' ` ;
svg += ` transform='scale( ${ c . scalex } , ${ c . scaley } ),translate( ${ c . offsetx } , ${ c . offsety } )'/> ` ;
}
svg += "</svg>" ;
let html = html _page _header ( ) ;
html += svg ;
html += "</body>" ;
html += "</html>" ;
let fwindow = frame . contentWindow ;
fwindow . document . open ( ) ;
fwindow . document . write ( html ) ;
fwindow . document . close ( ) ;
}