add LTO barcode generator App
This commit is contained in:
351
docs/lto-barcode/code39.js
Normal file
351
docs/lto-barcode/code39.js
Normal file
@ -0,0 +1,351 @@
|
||||
// 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
|
||||
|
||||
let code39_codes = {
|
||||
"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'],
|
||||
"*": ['b', 'S', 'b', 's', 'B', 's', 'B', 's', 'b']
|
||||
};
|
||||
|
||||
let colors = [
|
||||
'#BB282E',
|
||||
'#FAE54A',
|
||||
'#9AC653',
|
||||
'#01A5E2',
|
||||
'#9EAAB6',
|
||||
'#D97E35',
|
||||
'#E27B99',
|
||||
'#67A945',
|
||||
'#F6B855',
|
||||
'#705A81'
|
||||
];
|
||||
|
||||
let lto_label_width = 70;
|
||||
let lto_label_height = 17;
|
||||
|
||||
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 = "";
|
||||
|
||||
if (label.length != 6) {
|
||||
throw "wrong label length";
|
||||
}
|
||||
if (label_type.length != 2) {
|
||||
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;
|
||||
|
||||
if (mode === 'placeholder') {
|
||||
if (label_borders) {
|
||||
svg += `<rect class='unprintable' x='${pagex}' y='${pagey}' width='${lto_label_width}' height='${lto_label_height}' fill='none' style='stroke:black;stroke-width:0.1;'/>`;
|
||||
}
|
||||
return svg;
|
||||
}
|
||||
if (label_borders) {
|
||||
svg += `<rect x='${pagex}' y='${pagey}' width='${lto_label_width}' height='${lto_label_height}' fill='none' style='stroke:black;stroke-width:0.1;'/>`;
|
||||
}
|
||||
|
||||
if (mode === "color" || mode == "frame") {
|
||||
let w = lto_label_width/8;
|
||||
let h = lto_label_height - height;
|
||||
for (var i = 0; i < 7; i++) {
|
||||
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}*`;
|
||||
|
||||
for (var i = 0; i < raw_label.length; i++) {
|
||||
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 */
|
||||
html += "@media print { .unprintable { visibility: hidden; } }";
|
||||
|
||||
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);
|
||||
|
||||
let svg = svg_page_header( page_layout.page_width, page_layout.page_height);
|
||||
|
||||
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();
|
||||
}
|
||||
Reference in New Issue
Block a user