0

I'm currently creating a program where the user gives a text as input, and then gets displayed the same text with the Code 128 font to see his input as a barcode.

I already installed and located Code 128 and Code 39 under /usr/share/fonts/truetype/

Both fonts should be installed correctly because both work in Libre Office Writer. However, only Code 39 is displayed correctly in my JavaFx Application.

That's my code:

package sample;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;

public class CreateBarcodeStage extends Stage {

VBox vbox;

TextField textFieldInput;
TextFlow textFlowOutput;

public CreateBarcodeStage() {
    createUI();
    this.setTitle("Create Barcode");
    this.setScene(new Scene(vbox));
}

private void createUI() {
    vbox = new VBox(10);

    textFieldInput = new TextField();
    textFieldInput.textProperty().addListener((ObservableValue<? extends String> observableValue, String s, String t1) -> {
        String inputText = textFieldInput.getText();

        textFlowOutput.getChildren().clear();

        Text textReadable = new Text();
        textReadable.setFont(Font.font("Verdana", 20));
        textReadable.setText(inputText + "\n\n");

        Text textBarcode = new Text();
        textBarcode.setFont(Font.font("Code 128", 40));
        textBarcode.setText(inputText);

        textFlowOutput.getChildren().addAll(textReadable, textBarcode);
    });
    textFlowOutput = new TextFlow();
    textFlowOutput.setPadding(new Insets(15));
    textFlowOutput.setPrefWidth(200);
    textFlowOutput.setPrefHeight(150);


    vbox.getChildren().addAll(textFieldInput, textFlowOutput);

}
}

If I replace "Code 128" with "Code 39" everthing works fine.

This is the output with Code 39:

Code 39 output

And here is the output with Code 128:

Code 128 output

I don't know why Code 128 isn't displayed correctly.

EDIT: Ok, so now I tried to add an asterix before and after the Code 39 text and in this case everything works. I tested it with a barcode scanner app on my smartphone and the result was right.

For Code 128 I enhanced my code with a checksum maker which I found on github: github Code 128 barcode generator

Now my code looks like this:

package sample;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;

public class CreateBarcodeStage extends Stage {
VBox vbox;

TextField textFieldInput;
TextFlow textFlowOutput;

public CreateBarcodeStage() {
    createUI();
    this.setTitle("Create Barcode");
    this.setScene(new Scene(vbox));
}

private void createUI() {
    vbox = new VBox(10);

    textFieldInput = new TextField();
    textFieldInput.textProperty().addListener((ObservableValue<? extends String> observableValue, String s, String t1) -> {
        String inputText = textFieldInput.getText();

        textFlowOutput.getChildren().clear();

        Text textReadable = new Text();
        textReadable.setFont(Font.font("Verdana", 20));
        textReadable.setText(inputText + "\n\n");

        Text textBarcode = new Text();
        textBarcode.setFont(Font.font("Code 128", 40));
        textBarcode.setText(inputText);

        textFlowOutput.getChildren().addAll(textReadable, textBarcode);
    });
    textFlowOutput = new TextFlow();
    textFlowOutput.setPadding(new Insets(15));
    textFlowOutput.setPrefWidth(200);
    textFlowOutput.setPrefHeight(150);


    vbox.getChildren().addAll(textFieldInput, textFlowOutput);

}

private String createCode128(String text) {
    return (char) 136 + text + checksum(text) + (char) 138;
}

char checksum(String text) {
    int result = 104; // Code 128B start code
    for (int i = 0; i < text.length(); i++) {
        result += ((int) text.charAt(i) - 32) * (i + 1);
    }
    return (char) (result % 103 + 32); // Return the character value of the checksum.
    }
}

However, it still doesn't work: Code 128 with start/stop symbol and checksum

  • And you are using the same Code 128 font in Libre Office? – Brian Anderson Nov 11 '17 at 00:55
  • The only thing I can think of is the font is not 100% barcode symbols. For some reason your Code 128 font is mapping ASCII codes to human-readable characters and they've buried their bar symbols in high ASCII. Personally, I think it is a poor design decision to create a barcode font that requires unicode or high ASCII ($80-$FF) to work, but actually has symbols for the human-readable characters. Have you brought the font up in mapping software so you can see all the characters? – Brian Anderson Nov 11 '17 at 01:02

1 Answers1

0

While the output may look fine using the Code 39 font, it isn't. It will not scan and is not recognizable as a Code 39 barcode. This is what the word "TEXT" looks like in Code 39:

TEXT in Code 39

And this is what "TEXT" looks like with Code 128:

TEXT in Code 128

It looks like, with Code 39, you are missing the start and stop characters because what you are displaying in the Code 39 example is actually a subset of the bars, like so:

The code 39 bars from the screeshot, highlighted.

I suspect that with Code 128, you might not be supplying the start, stop and checksum characters, and the render is failing because of it.

Brian Anderson
  • 1,661
  • 1
  • 17
  • 27
  • Also, check to make sure you are passing low ASCII ($00-$7F) characters to Code 128. The font might not work with UTF-8 or UTF-16. Check the font's documentation. – Brian Anderson Nov 11 '17 at 00:53