Open BKM17061996 opened 4 years ago
What does the generated barcode look like after EVO has converted it to a PDF? Does it help if you specify the format? If JsBarcode produces the correct barcode in HTML then it seems this might be a bug with EVO rather than with JsBarcode.
I had the same problem with clj-htmltopdf as well. It works on the html but not on PDF. Is there anyway to set the svg by hand? Maybe a solution with Cavas?
Could you elaborate on what you're trying to accomplish (as opposed to how you're trying to do it)? Also what does an example barcode look like in the HTML vs. after conversion to PDF?
I've been experimenting with React PDF and have got something half working, but not yet usable:
import React from "react";
import {
Document,
Font,
G,
Page,
Rect,
StyleSheet,
Svg,
Text,
View
} from "@react-pdf/renderer";
import ReactPDF from "@react-pdf/renderer";
import JSBarcode from "jsbarcode";
/* Based on JsBarcode's svg.js etc. */
const merge = (old, replaceObj) => ({ ...old, ...replaceObj });
function getEncodingHeight(encoding, options) {
return options.height + options.marginTop + options.marginBottom;
}
function getBarcodePadding(textWidth, barcodeWidth, options) {
if (options.displayValue && barcodeWidth < textWidth) {
if (options.textAlign == "center") {
return Math.floor((textWidth - barcodeWidth) / 2);
} else if (options.textAlign == "left") {
return 0;
} else if (options.textAlign == "right") {
return Math.floor(textWidth - barcodeWidth);
}
}
return 0;
}
function calculateEncodingAttributes(encodings, barcodeOptions, context) {
for (let i = 0; i < encodings.length; i++) {
var encoding = encodings[i];
var options = merge(barcodeOptions, encoding.options);
var textWidth = 20;
var barcodeWidth = encoding.data.length * options.width;
encoding.width = Math.ceil(Math.max(textWidth, barcodeWidth));
encoding.height = getEncodingHeight(encoding, options);
encoding.barcodePadding = getBarcodePadding(
textWidth,
barcodeWidth,
options
);
}
}
function getTotalWidthOfEncodings(encodings) {
var totalWidth = 0;
for (let i = 0; i < encodings.length; i++) {
totalWidth += encodings[i].width;
}
return totalWidth;
}
function getMaximumHeightOfEncodings(encodings) {
var maxHeight = 0;
for (let i = 0; i < encodings.length; i++) {
if (encodings[i].height > maxHeight) {
maxHeight = encodings[i].height;
}
}
return maxHeight;
}
function Background(props) {
const { width, height, color } = props;
return (
<Rect x={0} y={0} width={width} height={height} style={{ fill: color }} />
);
}
function BarcodeChunk(props) {
const { binary, padding, options } = props;
// Creates the barcode out of the encoded binary
let yFrom;
if (options.textPosition == "top") {
yFrom = options.fontSize + options.textMargin;
} else {
yFrom = 0;
}
let barWidth = 0;
let x = 0;
let bars = [];
for (var b = 0; b < binary.length; b++) {
x = b * options.width + padding;
if (binary[b] === "1") {
barWidth++;
} else if (barWidth > 0) {
bars.push({
x: x - options.width * barWidth,
y: yFrom,
width: options.width * barWidth,
height: options.height
});
barWidth = 0;
}
}
// Last draw is needed since the barcode ends with 1
if (barWidth > 0) {
bars.push({
x: x - options.width * (barWidth - 1),
y: yFrom,
width: options.width * barWidth,
height: options.height
});
}
return bars.map((bar, i) => {
return (
<Rect key={i} x={bar.x} y={bar.y} width={bar.width} height={bar.height} />
);
});
}
function BarcodeText(props) {
const { text, width, padding, options } = props;
// Draw the text if displayValue is set
if (options.displayValue) {
var x, y, textAnchor;
if (options.textPosition == "top") {
y = options.fontSize - options.textMargin;
} else {
y = options.height + options.textMargin + options.fontSize;
}
// Draw the text in the correct X depending on the textAlign option
if (options.textAlign == "left" || padding > 0) {
x = 0;
textAnchor = "start";
} else if (options.textAlign == "right") {
x = width - 1;
textAnchor = "end";
}
// In all other cases, center the text
else {
x = width / 2;
textAnchor = "middle";
}
return (
<Text x={x} y={y} textAnchor={textAnchor} fill={options.lineColor}>
{text}
</Text>
);
} else {
return null;
}
}
function Barcode({ value, options }) {
let barcode = {};
JSBarcode(barcode, value, options);
let encodings = barcode.encodings;
const defaults = {
width: 2,
height: 100,
// format: "auto",
displayValue: true,
// fontOptions: "bold",
// font: "monospace",
text: "",
textAlign: "center",
textPosition: "bottom",
textMargin: 2,
// fontSize: 20,
background: "#ffffff",
lineColor: "#000000",
// margin: 10,
marginTop: 10,
marginBottom: 10,
marginLeft: 10,
marginRight: 10
// valid: function(){}
};
const mergedOptions = merge(defaults, options);
calculateEncodingAttributes(encodings, mergedOptions);
const totalWidth = getTotalWidthOfEncodings(encodings);
const maxHeight = getMaximumHeightOfEncodings(encodings);
const width =
totalWidth + mergedOptions.marginLeft + mergedOptions.marginRight;
let xs = [mergedOptions.marginLeft];
encodings.forEach((e) => xs.push(xs[xs.length - 1] + e.width));
return (
<Svg
x={0}
y={0}
width={width}
height={maxHeight}
viewBox={`0 0 ${width} ${maxHeight}`}
originX={0}
originY={0}
>
{options.background && (
<Background
width={width}
height={maxHeight}
color={options.background}
/>
)}
{encodings.map((encoding, i) => {
const encodingOptions = merge(options, encoding.options);
return (
<G
key={i}
x={xs[i]}
y={encodingOptions.marginTop}
fill={encodingOptions.lineColor}
>
<BarcodeChunk
binary={encoding.data}
padding={encoding.barcodePadding}
options={encodingOptions}
/>
<BarcodeText
text={encoding.text}
width={encoding.width}
padding={encoding.barcodePadding}
options={encodingOptions}
/>
</G>
);
})}
</Svg>
);
}
// Create styles
const styles = StyleSheet.create({
page: {
flexDirection: "row",
backgroundColor: "#E4E4E4"
},
section: {
margin: 10,
padding: 10,
flexGrow: 1
}
});
// Create Document Component
const MyDocument = () => (
<Document>
<Page size="A4" style={styles.page}>
<View style={styles.section}>
<Text>Section #1</Text>
<Barcode
value="123456789999"
options={{ format: "UPC", background: "lightblue" }}
/>
<Barcode
value="9501101530003"
options={{ format: "EAN13", background: "yellow" }}
/>
<Barcode
value="7895641245"
options={{ format: "CODE128", background: "pink" }}
/>
</View>
</Page>
</Document>
);
ReactPDF.render(<MyDocument />, `${__dirname}/../example.pdf`);
The CODE128 barcode scans fine, although the formatting is a bit off. The UPC and EAN13 barcodes are obviously completely broken.