barcodes working in pdf documents

This commit is contained in:
Jörg Prante 2021-02-26 23:52:19 +01:00
parent b4bee6e957
commit 139d43e6b4
79 changed files with 2399 additions and 1640 deletions

View file

@ -12,7 +12,11 @@ dependencies {
test {
useJUnitPlatform()
failFast = false
environment 'TMPDIR', '/var/tmp/gs'
systemProperty 'java.awt.headless', 'true'
systemProperty 'jna.debug', 'true'
//systemProperty 'jna.library.path', file('src/test/resources/').toString()
systemProperty 'java.util.logging.config.file', 'src/test/resources/logging.properties'
testLogging {
events 'STARTED', 'PASSED', 'FAILED', 'SKIPPED'
showStandardStreams = true

View file

@ -1,6 +1,10 @@
import org.xbib.graphics.barcode.Code3Of9;
import org.xbib.graphics.barcode.SymbolProvider;
module org.xbib.graphics.barcode {
exports org.xbib.graphics.barcode;
exports org.xbib.graphics.barcode.util;
exports org.xbib.graphics.barcode.render;
requires transitive java.desktop;
provides SymbolProvider with Code3Of9.Provider;
}

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,7 @@ import java.awt.geom.Rectangle2D;
/**
* Implements the <a href="http://auspost.com.au/media/documents/a-guide-to-printing-the-4state-barcode-v31-mar2012.pdf">Australia Post 4-State barcode</a>.
*/
public class AustraliaPost extends Symbol {
public class AustraliaPost extends AbstractSymbol {
private static final char[] CHARACTER_SET = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
@ -36,12 +36,11 @@ public class AustraliaPost extends Symbol {
"301", "302", "303", "310", "311", "312", "313", "320", "321", "322", "323", "330", "331",
"332", "333"
};
private ausMode mode;
;
private Mode mode;
public AustraliaPost() {
mode = ausMode.AUSPOST;
mode = Mode.AUSPOST;
}
/**
@ -102,7 +101,7 @@ public class AustraliaPost extends Symbol {
* </table>
*/
public void setPostMode() {
mode = ausMode.AUSPOST;
mode = Mode.AUSPOST;
}
/**
@ -110,7 +109,7 @@ public class AustraliaPost extends Symbol {
* 4-State Barcode (FCC 45) which requires an 8-digit DPID input.
*/
public void setReplyMode() {
mode = ausMode.AUSREPLY;
mode = Mode.AUSREPLY;
}
/**
@ -118,7 +117,7 @@ public class AustraliaPost extends Symbol {
* Barcode (FCC 87) which requires an 8-digit DPID input.
*/
public void setRouteMode() {
mode = ausMode.AUSROUTE;
mode = Mode.AUSROUTE;
}
/**
@ -126,7 +125,7 @@ public class AustraliaPost extends Symbol {
* Barcode (FCC 92) which requires an 8-digit DPID input.
*/
public void setRedirectMode() {
mode = ausMode.AUSREDIRECT;
mode = Mode.AUSREDIRECT;
}
@Override
@ -196,7 +195,7 @@ public class AustraliaPost extends Symbol {
encodeInfo.append("FCC: ").append(formatControlCode).append('\n');
if (mode != ausMode.AUSPOST) {
if (mode != Mode.AUSPOST) {
for (i = content.length(); i < 8; i++) {
zeroPaddedInput.append("0");
}
@ -324,7 +323,7 @@ public class AustraliaPost extends Symbol {
}
@Override
protected void plotSymbol() {
public void plotSymbol() {
int xBlock;
int x, y, w, h;
getRectangles().clear();
@ -359,5 +358,20 @@ public class AustraliaPost extends Symbol {
symbolHeight = 8;
}
private enum ausMode {AUSPOST, AUSREPLY, AUSROUTE, AUSREDIRECT}
private enum Mode {
AUSPOST, AUSREPLY, AUSROUTE, AUSREDIRECT
}
public static class Provider implements SymbolProvider<AustraliaPost> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.AUSTRALIA_POST;
}
@Override
public AustraliaPost provide() {
return new AustraliaPost();
}
}
}

View file

@ -9,7 +9,7 @@ import org.xbib.graphics.barcode.util.ReedSolomon;
* 3000 alphabetic characters or 1900 bytes of data in a two-dimensional matrix
* symbol.
*/
public class AztecCode extends Symbol {
public class AztecCode extends AbstractSymbol {
private static final int[] COMPACT_AZTEC_MAP = { //27 x 27 data grid
609, 608, 411, 413, 415, 417, 419, 421, 423, 425, 427, 429, 431, 433,
@ -586,7 +586,7 @@ public class AztecCode extends Symbol {
eciProcess(); // Get ECI mode
if ((inputDataType == DataType.GS1) && (readerInit)) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (readerInit)) {
errorMsg.append("Cannot encode in GS1 and Reader Initialisation mode at the same time");
return false;
}
@ -1236,7 +1236,7 @@ public class AztecCode extends Symbol {
/* Lookup input string in encoding table */
maplength = 0;
if (inputDataType == DataType.GS1) {
if (inputSymbolDataType == SymbolDataType.GS1) {
/* Add FNC1 to beginning of GS1 messages */
charmap[maplength] = 0; // FLG
typemap[maplength++] = 8; // PUNC
@ -1277,7 +1277,7 @@ public class AztecCode extends Symbol {
}
for (i = 0; i < inputBytes.length; i++) {
if ((inputDataType == DataType.GS1) && ((inputBytes[i] & 0xFF) == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && ((inputBytes[i] & 0xFF) == '[')) {
/* FNC1 represented by FLG(0) */
charmap[maplength] = 0; // FLG
typemap[maplength++] = 8; // PUNC
@ -1986,4 +1986,17 @@ public class AztecCode extends Symbol {
return binary.toString();
}
public static class Provider implements SymbolProvider<AztecCode> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.AUSTRALIA_POST;
}
@Override
public AztecCode provide() {
return new AztecCode();
}
}
}

View file

@ -8,7 +8,7 @@ import org.xbib.graphics.barcode.util.ReedSolomon;
* Aztec Runes is a fixed-size matrix symbology which can encode whole
* integer values between 0 and 255.
*/
public class AztecRune extends Symbol {
public class AztecRune extends AbstractSymbol {
private int[] bitPlacementMap = {
1, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1,
@ -165,4 +165,17 @@ public class AztecRune extends Symbol {
plotSymbol();
return true;
}
public static class Provider implements SymbolProvider<AztecRune> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.AZTEC_RUNE;
}
@Override
public AztecRune provide() {
return new AztecRune();
}
}
}

View file

@ -4,7 +4,7 @@ package org.xbib.graphics.barcode;
* Implements Channel Code according to ANSI/AIM BC12-1998.
* Channel code encodes whole integer values between 0 and 7,742,862.
*/
public class ChannelCode extends Symbol {
public class ChannelCode extends AbstractSymbol {
private int[] space = new int[11];
private int[] bar = new int[11];
private double currentValue;
@ -152,4 +152,17 @@ public class ChannelCode extends Symbol {
}
}
}
public static class Provider implements SymbolProvider<ChannelCode> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.CHANNEL_CODE;
}
@Override
public ChannelCode provide() {
return new ChannelCode();
}
}
}

View file

@ -8,7 +8,7 @@ package org.xbib.graphics.barcode;
* ($), colon (:), slash (/), full stop (.) or plus (+). No check digit is
* generated.
*/
public class Codabar extends Symbol {
public class Codabar extends AbstractSymbol {
private static final String[] CODABAR_TABLE = {
"11111221", "11112211", "11121121", "22111111", "11211211",
@ -83,4 +83,17 @@ public class Codabar extends Symbol {
protected int[] getCodewords() {
return getPatternAsCodewords(8);
}
public static class Provider implements SymbolProvider<Codabar> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.CODABAR;
}
@Override
public Codabar provide() {
return new Codabar();
}
}
}

View file

@ -9,10 +9,10 @@ import java.io.UnsupportedEncodingException;
* encode any 8-bit ISO 8859-1 (Latin-1) data up to approximately 1000
* alpha-numeric characters or 2000 numeric digits in length.
*/
public class CodablockF extends Symbol {
public class CodablockF extends AbstractSymbol {
/* Annex A Table A.1 */
private String[] C128Table = {"212222", "222122", "222221", "121223", "121322", "131222", "122213",
private final String[] c128Table = {"212222", "222122", "222221", "121223", "121322", "131222", "122213",
"122312", "132212", "221213", "221312", "231212", "112232", "122132", "122231", "113222",
"123122", "123221", "223211", "221132", "221231", "213212", "223112", "312131", "311222",
"321122", "321221", "312212", "322112", "322211", "212123", "212321", "232121", "111323",
@ -115,7 +115,7 @@ public class CodablockF extends Symbol {
k1_sum = 0;
k2_sum = 0;
for (i = 0; i < input_length; i++) {
if ((inputDataType == DataType.GS1) && source[i] == '[') {
if ((inputSymbolDataType == SymbolDataType.GS1) && source[i] == '[') {
k1_sum += (i + 1) * 29; /* GS */
k2_sum += i * 29;
} else {
@ -208,35 +208,35 @@ public class CodablockF extends Symbol {
row_pattern = new StringBuilder();
/* Start character */
row_pattern.append(C128Table[103]); /* Always Start A */
row_pattern.append(c128Table[103]); /* Always Start A */
switch (subset_selector[i]) {
case MODEA:
row_pattern.append(C128Table[98]);
row_pattern.append(c128Table[98]);
encodeInfo.append("MODEA ");
break;
case MODEB:
row_pattern.append(C128Table[100]);
row_pattern.append(c128Table[100]);
encodeInfo.append("MODEB ");
break;
case MODEC:
row_pattern.append(C128Table[99]);
row_pattern.append(c128Table[99]);
encodeInfo.append("MODEC ");
break;
}
row_pattern.append(C128Table[row_indicator[i]]);
encodeInfo.append(Integer.toString(row_indicator[i])).append(" ");
row_pattern.append(c128Table[row_indicator[i]]);
encodeInfo.append(row_indicator[i]).append(" ");
for (j = 0; j < columns_needed; j++) {
row_pattern.append(C128Table[blockmatrix[i][j]]);
encodeInfo.append(Integer.toString(blockmatrix[i][j])).append(" ");
row_pattern.append(c128Table[blockmatrix[i][j]]);
encodeInfo.append(blockmatrix[i][j]).append(" ");
}
row_pattern.append(C128Table[row_check[i]]);
encodeInfo.append("(").append(Integer.toString(row_check[i])).append(") ");
row_pattern.append(c128Table[row_check[i]]);
encodeInfo.append("(").append(row_check[i]).append(") ");
/* Stop character */
row_pattern.append(C128Table[106]);
row_pattern.append(c128Table[106]);
/* Write the information into the symbol */
pattern[i] = row_pattern.toString();
@ -293,7 +293,7 @@ public class CodablockF extends Symbol {
c = columns_needed;
current_mode = character_subset_select(input_position);
subset_selector[current_row] = current_mode;
if ((current_row == 0) && (inputDataType == DataType.GS1)) {
if ((current_row == 0) && (inputSymbolDataType == SymbolDataType.GS1)) {
/* Section 4.4.7.1 */
blockmatrix[current_row][column_position] = 102; /* FNC1 */
column_position++;
@ -301,7 +301,7 @@ public class CodablockF extends Symbol {
}
}
if ((inputDataType == DataType.GS1) && (source[input_position] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (source[input_position] == '[')) {
blockmatrix[current_row][column_position] = 102; /* FNC1 */
column_position++;
c--;
@ -487,7 +487,7 @@ public class CodablockF extends Symbol {
if (!done) {
if (((current_mode == cfMode.MODEA) || (current_mode == cfMode.MODEB))
&& ((findSubset(source[input_position]) == Mode.ABORC)
|| ((inputDataType == DataType.GS1) && (source[input_position] == '[')))) {
|| ((inputSymbolDataType == SymbolDataType.GS1) && (source[input_position] == '[')))) {
/* Count the number of numeric digits */
/* If 4 or more numeric data characters occur together when in subsets A or B:
a. If there is an even number of numeric data characters, insert a Code C character before the
@ -498,12 +498,12 @@ public class CodablockF extends Symbol {
j = 0;
do {
i++;
if ((inputDataType == DataType.GS1) && (source[input_position + j] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (source[input_position + j] == '[')) {
i++;
}
j++;
} while ((findSubset(source[input_position + j]) == Mode.ABORC)
|| ((inputDataType == DataType.GS1) && (source[input_position + j] == '[')));
|| ((inputSymbolDataType == SymbolDataType.GS1) && (source[input_position + j] == '[')));
i--;
if (i >= 4) {
@ -793,7 +793,7 @@ public class CodablockF extends Symbol {
}
@Override
protected void plotSymbol() {
public void plotSymbol() {
int xBlock, yBlock;
int x, y, w, h;
boolean black;
@ -849,4 +849,17 @@ public class CodablockF extends Symbol {
private enum cfMode {
MODEA, MODEB, MODEC
}
public static class Provider implements SymbolProvider<CodablockF> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.CODABLOCK_F;
}
@Override
public CodablockF provide() {
return new CodablockF();
}
}
}

View file

@ -5,7 +5,7 @@ package org.xbib.graphics.barcode;
* Code 11 can encode any length string consisting of the digits 0-9 and the
* dash character (-). One or two modulo-11 check digits are calculated.
*/
public class Code11 extends Symbol {
public class Code11 extends AbstractSymbol {
private static final String[] CODE_11_TABLE = {
"111121", "211121", "121121", "221111", "112121", "212111",
@ -205,4 +205,17 @@ public class Code11 extends Symbol {
protected int[] getCodewords() {
return getPatternAsCodewords(6);
}
public static class Provider implements SymbolProvider<Code11> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.CODE11;
}
@Override
public Code11 provide() {
return new Code11();
}
}
}

View file

@ -7,7 +7,7 @@ import java.io.UnsupportedEncodingException;
* Code 128 supports encoding of 8-bit ISO 8859-1 (Latin-1) characters.
* Setting GS1 mode allows encoding in GS1-128 (also known as UPC/EAN-128).
*/
public class Code128 extends Symbol {
public class Code128 extends AbstractSymbol {
private String[] code128Table = {
"212222", "222122", "222221", "121223", "121322", "131222", "122213",
"122312", "132212", "221213", "221312", "231212", "112232", "122132",
@ -163,7 +163,7 @@ public class Code128 extends Symbol {
mode_type[0] = mode;
mode_length[0] = 1;
if (inputDataType == DataType.GS1) {
if (inputSymbolDataType == SymbolDataType.GS1) {
mode = Mode.ABORC;
}
@ -174,7 +174,7 @@ public class Code128 extends Symbol {
for (i = 1; i < sourcelen; i++) {
last_mode = mode;
mode = findSubset(inputData[i]);
if ((inputDataType == DataType.GS1) && inputData[i] == '[') {
if ((inputSymbolDataType == SymbolDataType.GS1) && inputData[i] == '[') {
mode = Mode.ABORC;
}
if ((modeCSupression) && (mode == Mode.ABORC)) {
@ -193,7 +193,7 @@ public class Code128 extends Symbol {
reduceSubsetChanges();
if (inputDataType == DataType.GS1) {
if (inputSymbolDataType == SymbolDataType.GS1) {
/* Put set data into set[] */
read = 0;
for (i = 0; i < index_point; i++) {
@ -323,7 +323,7 @@ public class Code128 extends Symbol {
}
if (set[i] == Mode.LATCHC) {
if ((inputDataType == DataType.GS1) && (inputData[i] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (inputData[i] == '[')) {
glyph_count += 1.0;
} else {
glyph_count += 0.5;
@ -401,7 +401,7 @@ public class Code128 extends Symbol {
}
bar_characters++;
if (inputDataType == DataType.GS1) {
if (inputSymbolDataType == SymbolDataType.GS1) {
dest.append(code128Table[102]);
values[1] = 102;
bar_characters++;
@ -529,7 +529,7 @@ public class Code128 extends Symbol {
bar_characters++;
}
if (!((inputDataType == DataType.GS1) && (inputData[read] == '['))) {
if (!((inputSymbolDataType == SymbolDataType.GS1) && (inputData[read] == '['))) {
/* Encode data characters */
c = inputData[read];
switch (set[read]) {
@ -655,11 +655,11 @@ public class Code128 extends Symbol {
/* Stop character */
dest.append(code128Table[106]);
if (!(inputDataType == DataType.GS1)) {
if (!(inputSymbolDataType == SymbolDataType.GS1)) {
readable = new StringBuilder(content);
}
if (inputDataType == DataType.HIBC) {
if (inputSymbolDataType == SymbolDataType.HIBC) {
readable.append("*").append(content).append("*");
}
@ -839,5 +839,20 @@ public class Code128 extends Symbol {
SHIFTN, LATCHN, SHIFTF, LATCHF
}
private enum Composite {OFF, CCA, CCB, CCC}
private enum Composite {
OFF, CCA, CCB, CCC
}
public static class Provider implements SymbolProvider<Code128> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.CODE128;
}
@Override
public Code128 provide() {
return new Code128();
}
}
}

View file

@ -10,7 +10,7 @@ import java.io.UnsupportedEncodingException;
* of any 8-bit ISO 8859-1 (Latin-1) data with a maximum data capacity of 77
* alpha-numeric characters or 154 numerical digits.
*/
public class Code16k extends Symbol {
public class Code16k extends AbstractSymbol {
/* EN 12323 Table 1 - "Code 16K" character encodations */
private static final String[] C_16_K_TABLE = {
@ -137,7 +137,7 @@ public class Code16k extends Symbol {
indexchaine = 0;
mode = findSubset(inputData[indexchaine]);
if ((inputDataType == DataType.GS1) && (inputData[indexchaine] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (inputData[indexchaine] == '[')) {
mode = Mode.ABORC;
} /* FNC1 */
@ -152,7 +152,7 @@ public class Code16k extends Symbol {
indexchaine++;
if (indexchaine < input_length) {
mode = findSubset(inputData[indexchaine]);
if ((inputDataType == DataType.GS1) && (inputData[indexchaine] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (inputData[indexchaine] == '[')) {
mode = Mode.ABORC;
} /* FNC1 */
}
@ -280,14 +280,14 @@ public class Code16k extends Symbol {
}
}
if ((set[i] == 'C') && (!((inputDataType == DataType.GS1) && (content.charAt(i) == '[')))) {
if ((set[i] == 'C') && (!((inputSymbolDataType == SymbolDataType.GS1) && (content.charAt(i) == '[')))) {
glyph_count = glyph_count + 0.5;
} else {
glyph_count = glyph_count + 1.0;
}
}
if ((inputDataType == DataType.GS1) && (set[0] != 'A')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (set[0] != 'A')) {
/* FNC1 can be integrated with mode character */
glyph_count--;
}
@ -327,7 +327,7 @@ public class Code16k extends Symbol {
if (m == 2) {
m = 5;
}
if (inputDataType == DataType.GS1) {
if (inputSymbolDataType == SymbolDataType.GS1) {
errorMsg.append("Cannot use both GS1 mode and Reader Initialisation");
return false;
} else {
@ -339,7 +339,7 @@ public class Code16k extends Symbol {
values[bar_characters + 1] = 96; /* FNC3 */
bar_characters += 2;
} else {
if (inputDataType == DataType.GS1) {
if (inputSymbolDataType == SymbolDataType.GS1) {
/* Integrate FNC1 */
switch (set[0]) {
case 'B':
@ -461,7 +461,7 @@ public class Code16k extends Symbol {
bar_characters++;
}
if (!((inputDataType == DataType.GS1) && (inputData[read] == '['))) {
if (!((inputSymbolDataType == SymbolDataType.GS1) && (inputData[read] == '['))) {
switch (set[read]) { /* Encode data characters */
case 'A':
case 'a':
@ -712,7 +712,7 @@ public class Code16k extends Symbol {
}
@Override
protected void plotSymbol() {
public void plotSymbol() {
int xBlock, yBlock;
int x, y, w, h;
boolean black;
@ -766,4 +766,16 @@ public class Code16k extends Symbol {
NULL, SHIFTA, LATCHA, SHIFTB, LATCHB, SHIFTC, LATCHC, AORB, ABORC, CANDB, CANDBB
}
public static class Provider implements SymbolProvider<Code16k> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.CODE16K;
}
@Override
public Code16k provide() {
return new Code16k();
}
}
}

View file

@ -8,7 +8,7 @@ import java.awt.geom.Rectangle2D;
/**
* Implements the Code 2 of 5 family of barcode standards.
*/
public class Code2Of5 extends Symbol {
public class Code2Of5 extends AbstractSymbol {
private static final String[] C25_MATRIX_TABLE = {
"113311", "311131", "131131", "331111", "113131", "313111", "133111", "111331", "311311", "131311"
@ -419,7 +419,7 @@ public class Code2Of5 extends Symbol {
}
@Override
protected void plotSymbol() {
public void plotSymbol() {
int xBlock;
getRectangles().clear();
getTexts().clear();
@ -490,4 +490,17 @@ public class Code2Of5 extends Symbol {
private enum ToFMode {
MATRIX, INDUSTRIAL, IATA, DATA_LOGIC, INTERLEAVED, ITF14, DPLEIT, DPIDENT
}
public static class Provider implements SymbolProvider<Code2Of5> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.CODE25;
}
@Override
public Code2Of5 provide() {
return new Code2Of5();
}
}
}

View file

@ -6,7 +6,7 @@ package org.xbib.graphics.barcode;
* Requires a numeric input up to 8 digits in length. Check digit is
* calculated.
*/
public class Code32 extends Symbol {
public class Code32 extends AbstractSymbol {
private char[] tabella = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'B', 'C', 'D', 'F',
'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
@ -21,27 +21,22 @@ public class Code32 extends Symbol {
StringBuilder risultante;
int[] codeword = new int[6];
Code3Of9 c39 = new Code3Of9();
if (content.length() > 8) {
errorMsg.append("Input too long");
return false;
}
if (!(content.matches("[0-9]+"))) {
errorMsg.append("Invalid characters in input");
return false;
}
/* Add leading zeros as required */
localstr = new StringBuilder();
for (i = content.length(); i < 8; i++) {
localstr.append("0");
}
localstr.append(content);
/* Calculate the check digit */
checksum = 0;
checkpart = 0;
for (i = 0; i < 4; i++) {
checkpart = Character.getNumericValue(localstr.charAt(i * 2));
checksum += checkpart;
@ -52,7 +47,6 @@ public class Code32 extends Symbol {
checksum += checkpart;
}
}
/* Add check digit to data string */
checkdigit = checksum % 10;
localstr.append((char) (checkdigit + '0'));
@ -100,4 +94,17 @@ public class Code32 extends Symbol {
this.plotSymbol();
return true;
}
public static class Provider implements SymbolProvider<Code32> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.CODE32;
}
@Override
public Code32 provide() {
return new Code32();
}
}
}

View file

@ -7,7 +7,7 @@ package org.xbib.graphics.barcode;
* and percent (%). The standard does not require a check digit but a
* modulo-43 check digit can be added if required.
*/
public class Code3Of9 extends Symbol {
public class Code3Of9 extends AbstractSymbol {
private static final String[] CODE_39 = {
"1112212111", "2112111121", "1122111121", "2122111111", "1112211121",
@ -152,4 +152,17 @@ public class Code3Of9 extends Symbol {
public enum CheckDigit {
NONE, MOD43
}
public static class Provider implements SymbolProvider<Code3Of9> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.CODE39;
}
@Override
public Code3Of9 provide() {
return new Code3Of9();
}
}
}

View file

@ -5,7 +5,7 @@ package org.xbib.graphics.barcode;
* Supports encoding of all characters in the 7-bit ASCII table. A
* modulo-43 check digit can be added if required.
*/
public class Code3Of9Extended extends Symbol {
public class Code3Of9Extended extends AbstractSymbol {
private final String[] ECode39 = {
"%U", "$A", "$B", "$C", "$D", "$E", "$F", "$G", "$H", "$I", "$J", "$K",
@ -76,4 +76,17 @@ public class Code3Of9Extended extends Symbol {
public enum CheckDigit {
NONE, MOD43
}
public static class Provider implements SymbolProvider<Code3Of9Extended> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.CODE39_EXT;
}
@Override
public Code3Of9Extended provide() {
return new Code3Of9Extended();
}
}
}

View file

@ -7,7 +7,7 @@ import java.awt.geom.Rectangle2D;
* Encoding supports full 7-bit ASCII input up to a maximum of 49 characters
* or 81 numeric digits. GS1 data encoding is also supported.
*/
public class Code49 extends Symbol {
public class Code49 extends AbstractSymbol {
private final String[] c49_table7 = {
/* Table 7: Code 49 ASCII Chart */
@ -988,7 +988,7 @@ public class Code49 extends Symbol {
return false;
}
if (inputDataType == DataType.GS1) {
if (inputSymbolDataType == SymbolDataType.GS1) {
intermediate.append("*"); // FNC1
}
for (i = 0; i < length; i++) {
@ -996,7 +996,7 @@ public class Code49 extends Symbol {
errorMsg.append("Invalid characters in input");
return false;
}
if ((inputDataType == DataType.GS1) && (content.charAt(i) == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (content.charAt(i) == '[')) {
intermediate.append("*"); // FNC1
} else {
intermediate.append(c49_table7[content.charAt(i)]);
@ -1293,7 +1293,7 @@ public class Code49 extends Symbol {
}
@Override
protected void plotSymbol() {
public void plotSymbol() {
int xBlock, yBlock;
int x, y, w, h;
boolean black;
@ -1342,4 +1342,17 @@ public class Code49 extends Symbol {
symbolHeight += 2;
mergeVerticalBlocks();
}
public static class Provider implements SymbolProvider<Code49> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.CODE49;
}
@Override
public Code49 provide() {
return new Code49();
}
}
}

View file

@ -4,7 +4,7 @@ package org.xbib.graphics.barcode;
* Implements <a href="http://en.wikipedia.org/wiki/Code_93">Code 93</a>.
* Supports encoding of 7-bit ASCII text. Two check digits are added.
*/
public class Code93 extends Symbol {
public class Code93 extends AbstractSymbol {
/**
* Code 93 control characters, indexed by ASCII codes (NOTE: a = Ctrl $,
@ -189,4 +189,17 @@ public class Code93 extends Symbol {
protected int[] getCodewords() {
return getPatternAsCodewords(6);
}
public static class Provider implements SymbolProvider<Code93> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.CODE93;
}
@Override
public Code93 provide() {
return new Code93();
}
}
}

View file

@ -13,7 +13,7 @@ import java.math.BigInteger;
* The width of version S and version T symbols is determined by the length
* of the input data.
*/
public class CodeOne extends Symbol {
public class CodeOne extends AbstractSymbol {
private final int[] c40_shift = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@ -744,7 +744,7 @@ public class CodeOne extends Symbol {
text_p = 0;
edi_p = 0;
if (inputDataType == DataType.GS1) {
if (inputSymbolDataType == SymbolDataType.GS1) {
data[targetPoint] = 232;
targetPoint++;
} /* FNC1 */
@ -840,7 +840,7 @@ public class CodeOne extends Symbol {
}
if (!(isTwoDigits)) {
if ((inputDataType == DataType.GS1) && (source[sourcePoint] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (source[sourcePoint] == '[')) {
if ((length - sourcePoint) >= 15) { /* Step B4 */
j = 0;
@ -903,7 +903,7 @@ public class CodeOne extends Symbol {
sourcePoint++;
} else {
/* Step B8 */
if ((inputDataType == DataType.GS1) && (source[sourcePoint] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (source[sourcePoint] == '[')) {
data[targetPoint] = 232;
targetPoint++;
sourcePoint++; /* FNC1 */
@ -987,7 +987,7 @@ public class CodeOne extends Symbol {
value = c40_value[source[sourcePoint]];
}
if ((inputDataType == DataType.GS1) && (source[sourcePoint] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (source[sourcePoint] == '[')) {
shift_set = 2;
value = 27; /* FNC1 */
}
@ -1089,7 +1089,7 @@ public class CodeOne extends Symbol {
value = text_value[source[sourcePoint]];
}
if ((inputDataType == DataType.GS1) && (source[sourcePoint] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (source[sourcePoint] == '[')) {
shift_set = 2;
value = 27; /* FNC1 */
}
@ -1364,7 +1364,7 @@ public class CodeOne extends Symbol {
if (current_mode == c1Mode.C1_BYTE) {
next_mode = c1Mode.C1_BYTE;
if ((inputDataType == DataType.GS1) && (source[sourcePoint] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (source[sourcePoint] == '[')) {
next_mode = c1Mode.C1_ASCII;
} else {
if (source[sourcePoint] <= 127) {
@ -1677,7 +1677,7 @@ public class CodeOne extends Symbol {
}
/* Step P */
if ((inputDataType == DataType.GS1) && (source[sp] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (source[sp] == '[')) {
byte_count += 3.0;
} else {
byte_count += 1.0;
@ -1943,4 +1943,17 @@ public class CodeOne extends Symbol {
public enum Version {
NONE, A, B, C, D, E, F, G, H, S, T
}
public static class Provider implements SymbolProvider<CodeOne> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.CODEONE;
}
@Override
public CodeOne provide() {
return new CodeOne();
}
}
}

View file

@ -12,7 +12,7 @@ import java.util.List;
* and a "linear" element which can be UPC, EAN, Code 128 or
* GS1 DataBar symbol.
*/
public class Composite extends Symbol {
public class Composite extends AbstractSymbol {
/* CC-A component coefficients from ISO/IEC 24728:2006 Annex F */
private int[] ccaCoeffs = {
/* k = 4 */
@ -435,11 +435,11 @@ public class Composite extends Symbol {
private int linearWidth; // Width of Code 128 linear
public Composite() {
inputDataType = DataType.GS1;
inputSymbolDataType = SymbolDataType.GS1;
}
@Override
public void setDataType(DataType dummy) {
public void setDataType(SymbolDataType dummy) {
// Do nothing!
}
@ -555,7 +555,7 @@ public class Composite extends Symbol {
bottomShift = 7;
break;
}
code128.setDataType(DataType.GS1);
code128.setDataType(SymbolDataType.GS1);
code128.setContent(linearContent);
linearWidth = code128.symbolWidth;
linearRect = code128.getRectangles();
@ -2843,4 +2843,17 @@ public class Composite extends Symbol {
public enum CompositeMode {
CC_A, CC_B, CC_C
}
public static class Provider implements SymbolProvider<Composite> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.COMPOSITE;
}
@Override
public Composite provide() {
return new Composite();
}
}
}

View file

@ -7,7 +7,7 @@ import java.math.BigInteger;
* Input data should be a 13 digit Global Trade Identification Number
* without check digit or Application Identifier [01].
*/
public class DataBar14 extends Symbol {
public class DataBar14 extends AbstractSymbol {
private int[] g_sum_table = {
0, 161, 961, 2015, 2715, 0, 336, 1036, 1516
@ -49,7 +49,7 @@ public class DataBar14 extends Symbol {
}
@Override
public void setDataType(DataType dummy) {
public void setDataType(SymbolDataType dummy) {
// Do nothing!
}
@ -695,4 +695,17 @@ public class DataBar14 extends Symbol {
private enum gb14Mode {
LINEAR, OMNI, STACKED
}
public static class Provider implements SymbolProvider<DataBar14> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.DATABAR_14;
}
@Override
public DataBar14 provide() {
return new DataBar14();
}
}
}

View file

@ -6,7 +6,7 @@ package org.xbib.graphics.barcode;
* DataBar expanded encodes GS1 data in either a linear or stacked
* format.
*/
public class DataBarExpanded extends Symbol {
public class DataBarExpanded extends AbstractSymbol {
private static final int[] G_SUM_EXP = {
0, 348, 1388, 2948, 3988
@ -77,7 +77,7 @@ public class DataBarExpanded extends Symbol {
public DataBarExpanded() {
linkageFlag = false;
inputDataType = DataType.GS1;
inputSymbolDataType = SymbolDataType.GS1;
}
private static int calculateRemainder(int binaryStringLength) {
@ -104,7 +104,7 @@ public class DataBarExpanded extends Symbol {
;
@Override
public void setDataType(DataType dummy) {
public void setDataType(SymbolDataType dummy) {
// Do nothing!
}
@ -1649,4 +1649,17 @@ public class DataBarExpanded extends Symbol {
private enum EncodeMode {
NUMERIC, ALPHA, ISOIEC, INVALID_CHAR, ANY_ENC, ALPHA_OR_ISO
}
public static class Provider implements SymbolProvider<DataBarExpanded> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.DATABAR_EXPANDED;
}
@Override
public DataBarExpanded provide() {
return new DataBarExpanded();
}
}
}

View file

@ -7,7 +7,7 @@ import java.math.BigInteger;
* Input data should be a 12 digit Global Trade Identification Number
* without check digit or Application Identifier [01].
*/
public class DataBarLimited extends Symbol {
public class DataBarLimited extends AbstractSymbol {
private static final int[] t_even_ltd = {
28, 728, 6454, 203, 2408, 1, 16632
@ -128,7 +128,7 @@ public class DataBarLimited extends Symbol {
}
@Override
public void setDataType(DataType dummy) {
public void setDataType(SymbolDataType dummy) {
// Do nothing!
}
@ -473,4 +473,17 @@ public class DataBarLimited extends Symbol {
}
widths[bar] = n;
}
public static class Provider implements SymbolProvider<DataBarLimited> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.DATABAR_LIMITED;
}
@Override
public DataBarLimited provide() {
return new DataBarLimited();
}
}
}

View file

@ -8,7 +8,7 @@ import org.xbib.graphics.barcode.util.ReedSolomon;
* Data Matrix is a 2D matrix symbology capable of encoding characters in the
* ISO/IEC 8859-1 (Latin-1) character set.
*/
public class DataMatrix extends Symbol {
public class DataMatrix extends AbstractSymbol {
private static final int[] c40_shift = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@ -90,7 +90,7 @@ public class DataMatrix extends Symbol {
private int[] target = new int[2200];
private int[] binary = new int[2200];
private int binary_length;
private dm_mode last_mode;
private Mode last_mode;
private int[] places;
private boolean isSquare;
private int[] inputData;
@ -441,7 +441,7 @@ public class DataMatrix extends Symbol {
encodeInfo.append("Encoding: ");
int sp, tp, i;
dm_mode current_mode, next_mode;
Mode current_mode, next_mode;
int inputlen = content.length();
sp = 0;
@ -454,10 +454,10 @@ public class DataMatrix extends Symbol {
binary_length = 0;
/* step (a) */
current_mode = dm_mode.DM_ASCII;
next_mode = dm_mode.DM_ASCII;
current_mode = Mode.DM_ASCII;
next_mode = Mode.DM_ASCII;
if (inputDataType == DataType.GS1) {
if (inputSymbolDataType == SymbolDataType.GS1) {
target[tp] = 232;
tp++;
binary[binary_length] = ' ';
@ -494,7 +494,7 @@ public class DataMatrix extends Symbol {
}
if (readerInit) {
if (inputDataType == DataType.GS1) {
if (inputSymbolDataType == SymbolDataType.GS1) {
errorMsg.append("Cannot encode in GS1 mode and Reader Initialisation at the same time");
return 0;
} else {
@ -539,8 +539,8 @@ public class DataMatrix extends Symbol {
current_mode = next_mode;
/* step (b) - ASCII encodation */
if (current_mode == dm_mode.DM_ASCII) {
next_mode = dm_mode.DM_ASCII;
if (current_mode == Mode.DM_ASCII) {
next_mode = Mode.DM_ASCII;
for (i = 0; i < 8; i++) {
process_buffer[i] = 0;
@ -557,7 +557,7 @@ public class DataMatrix extends Symbol {
} else {
next_mode = lookAheadTest(sp, current_mode);
if (next_mode != dm_mode.DM_ASCII) {
if (next_mode != Mode.DM_ASCII) {
switch (next_mode) {
case DM_C40:
target[tp] = 230;
@ -609,7 +609,7 @@ public class DataMatrix extends Symbol {
binary[binary_length] = ' ';
binary_length++;
} else {
if ((inputDataType == DataType.GS1) && (inputData[sp] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (inputData[sp] == '[')) {
target[tp] = 232; /* FNC1 */
encodeInfo.append("FNC1 ");
} else {
@ -627,21 +627,21 @@ public class DataMatrix extends Symbol {
}
/* step (c) C40 encodation */
if (current_mode == dm_mode.DM_C40) {
if (current_mode == Mode.DM_C40) {
int shift_set, value;
next_mode = dm_mode.DM_C40;
next_mode = Mode.DM_C40;
if (process_p == 0) {
next_mode = lookAheadTest(sp, current_mode);
}
if (next_mode != dm_mode.DM_C40) {
if (next_mode != Mode.DM_C40) {
target[tp] = 254;
tp++;
binary[binary_length] = ' ';
binary_length++; /* Unlatch */
next_mode = dm_mode.DM_ASCII;
next_mode = Mode.DM_ASCII;
encodeInfo.append("ASC ");
} else {
if (inputData[sp] > 127) {
@ -657,7 +657,7 @@ public class DataMatrix extends Symbol {
value = c40_value[inputData[sp]];
}
if ((inputDataType == DataType.GS1) && (inputData[sp] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (inputData[sp] == '[')) {
shift_set = 2;
value = 27; /* FNC1 */
@ -701,21 +701,21 @@ public class DataMatrix extends Symbol {
}
/* step (d) Text encodation */
if (current_mode == dm_mode.DM_TEXT) {
if (current_mode == Mode.DM_TEXT) {
int shift_set, value;
next_mode = dm_mode.DM_TEXT;
next_mode = Mode.DM_TEXT;
if (process_p == 0) {
next_mode = lookAheadTest(sp, current_mode);
}
if (next_mode != dm_mode.DM_TEXT) {
if (next_mode != Mode.DM_TEXT) {
target[tp] = 254;
tp++;
binary[binary_length] = ' ';
binary_length++; /* Unlatch */
next_mode = dm_mode.DM_ASCII;
next_mode = Mode.DM_ASCII;
encodeInfo.append("ASC ");
} else {
if (inputData[sp] > 127) {
@ -731,7 +731,7 @@ public class DataMatrix extends Symbol {
value = text_value[inputData[sp]];
}
if ((inputDataType == DataType.GS1) && (inputData[sp] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (inputData[sp] == '[')) {
shift_set = 2;
value = 27; /* FNC1 */
@ -774,21 +774,21 @@ public class DataMatrix extends Symbol {
}
/* step (e) X12 encodation */
if (current_mode == dm_mode.DM_X12) {
if (current_mode == Mode.DM_X12) {
int value = 0;
next_mode = dm_mode.DM_X12;
next_mode = Mode.DM_X12;
if (process_p == 0) {
next_mode = lookAheadTest(sp, current_mode);
}
if (next_mode != dm_mode.DM_X12) {
if (next_mode != Mode.DM_X12) {
target[tp] = 254;
tp++;
binary[binary_length] = ' ';
binary_length++; /* Unlatch */
next_mode = dm_mode.DM_ASCII;
next_mode = Mode.DM_ASCII;
encodeInfo.append("ASC ");
} else {
if (inputData[sp] == 13) {
@ -843,18 +843,18 @@ public class DataMatrix extends Symbol {
}
/* step (f) EDIFACT encodation */
if (current_mode == dm_mode.DM_EDIFACT) {
if (current_mode == Mode.DM_EDIFACT) {
int value = 0;
next_mode = dm_mode.DM_EDIFACT;
next_mode = Mode.DM_EDIFACT;
if (process_p == 3) {
next_mode = lookAheadTest(sp, current_mode);
}
if (next_mode != dm_mode.DM_EDIFACT) {
if (next_mode != Mode.DM_EDIFACT) {
process_buffer[process_p] = 31;
process_p++;
next_mode = dm_mode.DM_ASCII;
next_mode = Mode.DM_ASCII;
} else {
if ((inputData[sp] >= '@') && (inputData[sp] <= '^')) {
value = inputData[sp] - '@';
@ -901,10 +901,10 @@ public class DataMatrix extends Symbol {
}
/* step (g) Base 256 encodation */
if (current_mode == dm_mode.DM_BASE256) {
if (current_mode == Mode.DM_BASE256) {
next_mode = lookAheadTest(sp, current_mode);
if (next_mode == dm_mode.DM_BASE256) {
if (next_mode == Mode.DM_BASE256) {
target[tp] = inputData[sp];
encodeInfo.append(Integer.toString(target[tp])).append(" ");
tp++;
@ -912,7 +912,7 @@ public class DataMatrix extends Symbol {
binary[binary_length] = 'b';
binary_length++;
} else {
next_mode = dm_mode.DM_ASCII;
next_mode = Mode.DM_ASCII;
encodeInfo.append("ASC ");
}
}
@ -1133,16 +1133,16 @@ public class DataMatrix extends Symbol {
return false;
}
private dm_mode lookAheadTest(int position, dm_mode current_mode) {
private Mode lookAheadTest(int position, Mode current_mode) {
/* 'look ahead test' from Annex P */
double ascii_count, c40_count, text_count, x12_count, edf_count, b256_count, best_count;
int sp;
int sourcelen = content.length();
dm_mode best_scheme = dm_mode.NULL;
Mode best_scheme = Mode.NULL;
/* step (j) */
if (current_mode == dm_mode.DM_ASCII) {
if (current_mode == Mode.DM_ASCII) {
ascii_count = 0.0;
c40_count = 1.0;
text_count = 1.0;
@ -1189,30 +1189,30 @@ public class DataMatrix extends Symbol {
c40_count = Math.ceil(c40_count);
best_count = c40_count;
best_scheme = dm_mode.DM_C40; // (k)(7)
best_scheme = Mode.DM_C40; // (k)(7)
if (x12_count < best_count) {
best_count = x12_count;
best_scheme = dm_mode.DM_X12; // (k)(6)
best_scheme = Mode.DM_X12; // (k)(6)
}
if (text_count < best_count) {
best_count = text_count;
best_scheme = dm_mode.DM_TEXT; // (k)(5)
best_scheme = Mode.DM_TEXT; // (k)(5)
}
if (edf_count < best_count) {
best_count = edf_count;
best_scheme = dm_mode.DM_EDIFACT; // (k)(4)
best_scheme = Mode.DM_EDIFACT; // (k)(4)
}
if (b256_count < best_count) {
best_count = b256_count;
best_scheme = dm_mode.DM_BASE256; // (k)(3)
best_scheme = Mode.DM_BASE256; // (k)(3)
}
if (ascii_count <= best_count) {
best_scheme = dm_mode.DM_ASCII; // (k)(2)
best_scheme = Mode.DM_ASCII; // (k)(2)
}
} else {
@ -1274,12 +1274,12 @@ public class DataMatrix extends Symbol {
edf_count += (13.0 / 4.0); // (p)(3)
}
}
if ((inputDataType == DataType.GS1) && (inputData[sp] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (inputData[sp] == '[')) {
edf_count += 6.0;
}
/* base 256 ... step (q) */
if ((inputDataType == DataType.GS1) && (inputData[sp] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (inputData[sp] == '[')) {
b256_count += 4.0; // (q)(1)
} else {
b256_count += 1.0; // (q)(2)
@ -1297,15 +1297,15 @@ public class DataMatrix extends Symbol {
((c40_count + 1.0) < text_count)) {
if (c40_count < x12_count) {
best_scheme = dm_mode.DM_C40;
best_scheme = Mode.DM_C40;
}
if (c40_count == x12_count) {
if (p_r_6_2_1(sp, sourcelen)) {
// Test (r)(6)(ii)(i)
best_scheme = dm_mode.DM_X12;
best_scheme = Mode.DM_X12;
} else {
best_scheme = dm_mode.DM_C40;
best_scheme = Mode.DM_C40;
}
}
}
@ -1316,7 +1316,7 @@ public class DataMatrix extends Symbol {
((x12_count + 1.0) < edf_count) &&
((x12_count + 1.0) < text_count) &&
((x12_count + 1.0) < c40_count)) {
best_scheme = dm_mode.DM_X12;
best_scheme = Mode.DM_X12;
}
/* step (r)(4) */
@ -1325,7 +1325,7 @@ public class DataMatrix extends Symbol {
((text_count + 1.0) < edf_count) &&
((text_count + 1.0) < x12_count) &&
((text_count + 1.0) < c40_count)) {
best_scheme = dm_mode.DM_TEXT;
best_scheme = Mode.DM_TEXT;
}
/* step (r)(3) */
@ -1334,7 +1334,7 @@ public class DataMatrix extends Symbol {
((edf_count + 1.0) < text_count) &&
((edf_count + 1.0) < x12_count) &&
((edf_count + 1.0) < c40_count)) {
best_scheme = dm_mode.DM_EDIFACT;
best_scheme = Mode.DM_EDIFACT;
}
/* step (r)(2) */
@ -1343,7 +1343,7 @@ public class DataMatrix extends Symbol {
((b256_count + 1.0) < text_count) &&
((b256_count + 1.0) < x12_count) &&
((b256_count + 1.0) < c40_count))) {
best_scheme = dm_mode.DM_BASE256;
best_scheme = Mode.DM_BASE256;
}
/* step (r)(1) */
@ -1352,12 +1352,12 @@ public class DataMatrix extends Symbol {
((ascii_count + 1.0) <= text_count) &&
((ascii_count + 1.0) <= x12_count) &&
((ascii_count + 1.0) <= c40_count)) {
best_scheme = dm_mode.DM_ASCII;
best_scheme = Mode.DM_ASCII;
}
}
sp++;
} while (best_scheme == dm_mode.NULL); // step (s)
} while (best_scheme == Mode.NULL); // step (s)
return best_scheme;
}
@ -1629,8 +1629,21 @@ public class DataMatrix extends Symbol {
places[r * NC + c] = (p << 3) + b;
}
private enum dm_mode {
private enum Mode {
NULL, DM_ASCII, DM_C40, DM_TEXT, DM_X12, DM_EDIFACT, DM_BASE256
}
public static class Provider implements SymbolProvider<DataMatrix> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.DATA_MATRIX;
}
@Override
public DataMatrix provide() {
return new DataMatrix();
}
}
}

View file

@ -14,7 +14,7 @@ import java.awt.geom.Rectangle2D;
* generally for internal use only. Check digit is calculated and should not
* be in input data. Leading zeroes are added as required.
*/
public class Ean extends Symbol {
public class Ean extends AbstractSymbol {
private boolean useAddOn;
@ -244,7 +244,7 @@ public class Ean extends Symbol {
}
@Override
protected void plotSymbol() {
public void plotSymbol() {
int xBlock;
int x, y, w, h;
boolean black;
@ -363,4 +363,17 @@ public class Ean extends Symbol {
public enum Mode {
EAN8, EAN13
}
public static class Provider implements SymbolProvider<Ean> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.EAN;
}
@Override
public Ean provide() {
return new Ean();
}
}
}

View file

@ -9,7 +9,7 @@ import java.io.UnsupportedEncodingException;
* 8859-1 (Latin-1) character set as well as those in the GB-2312 character set.
* Input is assumed to be formatted as a UTF string.
*/
public class GridMatrix extends Symbol {
public class GridMatrix extends AbstractSymbol {
private final char[] shift_set = {
/* From Table 7 - Encoding of control characters */
@ -2012,4 +2012,17 @@ public class GridMatrix extends Symbol {
NULL, GM_NUMBER, GM_LOWER, GM_UPPER, GM_MIXED, GM_CONTROL, GM_BYTE, GM_CHINESE
}
public static class Provider implements SymbolProvider<GridMatrix> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.GRID_MATRIX;
}
@Override
public GridMatrix provide() {
return new GridMatrix();
}
}
}

View file

@ -9,7 +9,7 @@ import java.util.Locale;
* characters A-Z and the dash (-) character. A modulo-19 check digit is
* added and should not be included in the input data.
*/
public class JapanPost extends Symbol {
public class JapanPost extends AbstractSymbol {
private static final String[] JAPAN_TABLE = {
"FFT", "FDA", "DFA", "FAD", "FTF", "DAF", "AFD", "ADF", "TFF", "FTT",
@ -101,7 +101,7 @@ public class JapanPost extends Symbol {
}
@Override
protected void plotSymbol() {
public void plotSymbol() {
int xBlock;
int x, y, w, h;
getRectangles().clear();
@ -135,4 +135,17 @@ public class JapanPost extends Symbol {
symbolWidth = pattern[0].length() * 3;
symbolHeight = 8;
}
public static class Provider implements SymbolProvider<JapanPost> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.JAPAN_POST;
}
@Override
public JapanPost provide() {
return new JapanPost();
}
}
}

View file

@ -8,7 +8,7 @@ import java.util.Locale;
* (Netherlands). Input data can consist of digits 0-9 and characters A-Z.
* Input should be 11 characters in length. No check digit is added.
*/
public class KixCode extends Symbol {
public class KixCode extends AbstractSymbol {
/* Handles Dutch Post TNT KIX symbols */
/* The same as RM4SCC but without check digit */
@ -58,7 +58,7 @@ public class KixCode extends Symbol {
}
@Override
protected void plotSymbol() {
public void plotSymbol() {
int xBlock;
int x, y, w, h;
getRectangles().clear();
@ -92,4 +92,17 @@ public class KixCode extends Symbol {
symbolWidth = pattern[0].length() * 3;
symbolHeight = 8;
}
public static class Provider implements SymbolProvider<KixCode> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.KIX_CODE;
}
@Override
public KixCode provide() {
return new KixCode();
}
}
}

View file

@ -5,7 +5,7 @@ package org.xbib.graphics.barcode;
* number. A Modulo-10 check digit is calculated and added, and should not form
* part of the input data.
*/
public class KoreaPost extends Symbol {
public class KoreaPost extends AbstractSymbol {
String[] koreaTable = {
"1313150613", "0713131313", "0417131313", "1506131313", "0413171313",
@ -58,4 +58,17 @@ public class KoreaPost extends Symbol {
plotSymbol();
return true;
}
public static class Provider implements SymbolProvider<KoreaPost> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.KOREA_POST;
}
@Override
public KoreaPost provide() {
return new KoreaPost();
}
}
}

View file

@ -8,7 +8,7 @@ package org.xbib.graphics.barcode;
* A Modulo-43 check digit is calculated and added, and should not form part
* of the input data.
*/
public class Logmars extends Symbol {
public class Logmars extends AbstractSymbol {
private static final String[] CODE39LM = {
"1113313111", "3113111131", "1133111131", "3133111111", "1113311131",
@ -94,4 +94,17 @@ public class Logmars extends Symbol {
plotSymbol();
return true;
}
public static class Provider implements SymbolProvider<Logmars> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.LOG_MARS;
}
@Override
public Logmars provide() {
return new Logmars();
}
}
}

View file

@ -13,7 +13,7 @@ import java.util.Arrays;
* any from the ISO 8859-1 (Latin-1) character set.
* TODO: Add ECI functionality.
*/
public class MaxiCode extends Symbol {
public class MaxiCode extends AbstractSymbol {
/**
* MaxiCode module sequence, from ISO/IEC 16023 Figure 5 (30 x 33 data grid).
@ -851,8 +851,7 @@ public class MaxiCode extends Symbol {
}
@Override
protected void plotSymbol() {
public void plotSymbol() {
// hexagons
for (int row = 0; row < 33; row++) {
for (int col = 0; col < 30; col++) {
@ -866,7 +865,6 @@ public class MaxiCode extends Symbol {
}
}
}
// circles
double[] radii = {10.85, 8.97, 7.10, 5.22, 3.31, 1.43};
for (double aRadii : radii) {
@ -880,4 +878,17 @@ public class MaxiCode extends Symbol {
protected int[] getCodewords() {
return codewords;
}
public static class Provider implements SymbolProvider<MaxiCode> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.MAXI_CODE;
}
@Override
public MaxiCode provide() {
return new MaxiCode();
}
}
}

View file

@ -10,7 +10,7 @@ import java.io.UnsupportedEncodingException;
* QR Code symbols can encode characters in the Latin-1 set and Kanji
* characters which are members of the Shift-JIS encoding scheme.
*/
public class MicroQrCode extends Symbol {
public class MicroQrCode extends AbstractSymbol {
/* Table 5 - Encoding/Decoding table for Alphanumeric mode */
private static final char[] RHODIUM = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
@ -1590,4 +1590,17 @@ public class MicroQrCode extends Symbol {
public enum EccMode {
L, M, Q, H
}
public static class Provider implements SymbolProvider<MicroQrCode> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.MICRO_QRCODE;
}
@Override
public MicroQrCode provide() {
return new MicroQrCode();
}
}
}

View file

@ -5,7 +5,7 @@ package org.xbib.graphics.barcode;
* MSI Plessey can encode a string of numeric digits and has a range
* of check digit options.
*/
public class MsiPlessey extends Symbol {
public class MsiPlessey extends AbstractSymbol {
private final String[] MSI_PlessTable = {
"12121212", "12121221", "12122112", "12122121", "12211212", "12211221",
@ -185,4 +185,17 @@ public class MsiPlessey extends Symbol {
public enum CheckDigit {
NONE, MOD10, MOD10_MOD10, MOD11, MOD11_MOD10
}
public static class Provider implements SymbolProvider<MsiPlessey> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.MSI_PLESSEY;
}
@Override
public MsiPlessey provide() {
return new MsiPlessey();
}
}
}

View file

@ -7,7 +7,7 @@ import java.util.stream.IntStream;
* Also SSCC-18 (Serial Shipping Container Code)
* Encodes a 17 digit number, adding a Modulo-10 check digit.
*/
public class Nve18 extends Symbol {
public class Nve18 extends AbstractSymbol {
@Override
public boolean encode() {
@ -51,7 +51,7 @@ public class Nve18 extends Symbol {
content = "[00]" + gs1Equivalent + cdigit;
// Defer to Code 128
code128.setDataType(DataType.GS1);
code128.setDataType(SymbolDataType.GS1);
code128.setHumanReadableLocation(getHumanReadableLocation());
try {
@ -69,4 +69,17 @@ public class Nve18 extends Symbol {
encodeInfo.append(code128.encodeInfo);
return true;
}
public static class Provider implements SymbolProvider<Nve18> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.NVE_18;
}
@Override
public Nve18 provide() {
return new Nve18();
}
}
}

View file

@ -12,7 +12,7 @@ import java.util.List;
* of 1850 text characters, or 2710 digits. The maximum size MicroPDF417 symbol
* can hold 250 alphanumeric characters or 366 digits.
*/
public class Pdf417 extends Symbol {
public class Pdf417 extends AbstractSymbol {
private static final int MAX_NUMERIC_COMPACTION_BLOCK_SIZE = 44;
@ -1701,4 +1701,17 @@ public class Pdf417 extends Symbol {
return mode + "x" + length;
}
}
public static class Provider implements SymbolProvider<Pdf417> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.PDF417;
}
@Override
public Pdf417 provide() {
return new Pdf417();
}
}
}

View file

@ -6,7 +6,7 @@ package org.xbib.graphics.barcode;
* Pharmacode is used for the identification of pharmaceuticals. The symbology
* is able to encode whole numbers between 3 and 131070.
*/
public class Pharmacode extends Symbol {
public class Pharmacode extends AbstractSymbol {
@Override
public boolean encode() {
@ -63,4 +63,17 @@ public class Pharmacode extends Symbol {
plotSymbol();
return true;
}
public static class Provider implements SymbolProvider<Pharmacode> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.PHARMACODE;
}
@Override
public Pharmacode provide() {
return new Pharmacode();
}
}
}

View file

@ -8,7 +8,7 @@ import java.awt.geom.Rectangle2D;
* for the identification of pharmaceuticals. The symbology is able to encode
* whole numbers between 4 and 64570080.
*/
public class Pharmacode2Track extends Symbol {
public class Pharmacode2Track extends AbstractSymbol {
@Override
public boolean encode() {
@ -73,7 +73,7 @@ public class Pharmacode2Track extends Symbol {
}
@Override
protected void plotSymbol() {
public void plotSymbol() {
int xBlock;
int x, y, w, h;
getRectangles().clear();
@ -103,4 +103,17 @@ public class Pharmacode2Track extends Symbol {
symbolWidth = pattern[0].length() * 2;
symbolHeight = defaultHeight;
}
public static class Provider implements SymbolProvider<Pharmacode2Track> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.PHARMACODE2TRACK;
}
@Override
public Pharmacode2Track provide() {
return new Pharmacode2Track();
}
}
}

View file

@ -4,7 +4,7 @@ package org.xbib.graphics.barcode;
* PZN8 is a Code 39 based symbology used by the pharmaceutical industry in
* Germany. PZN8 encodes a 7 digit number and includes a modulo-10 check digit.
*/
public class Pharmazentralnummer extends Symbol {
public class Pharmazentralnummer extends AbstractSymbol {
/* Pharmazentral Nummer is a Code 3 of 9 symbol with an extra
* check digit. Now generates PZN-8.
@ -66,4 +66,17 @@ public class Pharmazentralnummer extends Symbol {
plotSymbol();
return true;
}
public static class Provider implements SymbolProvider<Pharmazentralnummer> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.PHARMAZENTRALNUMMER;
}
@Override
public Pharmazentralnummer provide() {
return new Pharmazentralnummer();
}
}
}

View file

@ -12,16 +12,16 @@ import java.awt.geom.Rectangle2D;
* POSTNET and PLANET both use numerical input data and include a modulo-10
* check digit.
*/
public class Postnet extends Symbol {
public class Postnet extends AbstractSymbol {
private static final String[] PN_TABLE = {
"LLSSS", "SSSLL", "SSLSL", "SSLLS", "SLSSL", "SLSLS", "SLLSS", "LSSSL", "LSSLS", "LSLSS"
};
;
private static final String[] PL_TABLE = {
"SSLLL", "LLLSS", "LLSLS", "LLSSL", "LSLLS", "LSLSL", "LSSLL", "SLLLS", "SLLSL", "SLSLL"
};
private Mode mode;
public Postnet() {
@ -140,7 +140,7 @@ public class Postnet extends Symbol {
}
@Override
protected void plotSymbol() {
public void plotSymbol() {
int xBlock, shortHeight;
double x, y, w, h;
getRectangles().clear();
@ -182,4 +182,17 @@ public class Postnet extends Symbol {
public enum Mode {
PLANET, POSTNET
}
public static class Provider implements SymbolProvider<Postnet> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.POSTNET;
}
@Override
public Postnet provide() {
return new Postnet();
}
}
}

View file

@ -11,7 +11,7 @@ import java.io.UnsupportedEncodingException;
* Latin-1 set and Kanji characters which are members of the Shift-JIS encoding
* scheme.
*/
public class QrCode extends Symbol {
public class QrCode extends AbstractSymbol {
/* Table 5 - Encoding/Decoding table for Alphanumeric mode */
private final char[] rhodium = {
@ -658,7 +658,7 @@ public class QrCode extends Symbol {
if (isXAlpha((char) (inputData[i] & 0xFF))) {
inputMode[i] = qrMode.ALPHANUM;
}
if ((inputDataType == DataType.GS1) && (inputData[i] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (inputData[i] == '[')) {
inputMode[i] = qrMode.ALPHANUM;
}
if (isXNumeric((char) (inputData[i] & 0xff))) {
@ -682,7 +682,7 @@ public class QrCode extends Symbol {
count += 12;
}
if (inputDataType == DataType.GS1) {
if (inputSymbolDataType == SymbolDataType.GS1) {
count += 4;
}
@ -924,7 +924,7 @@ public class QrCode extends Symbol {
count += 12;
}
if (inputDataType == DataType.GS1) {
if (inputSymbolDataType == SymbolDataType.GS1) {
count += 4;
}
@ -1031,7 +1031,7 @@ public class QrCode extends Symbol {
}
}
if (inputDataType == DataType.GS1) {
if (inputSymbolDataType == SymbolDataType.GS1) {
binary.append("0101"); /* FNC1 */
}
@ -1137,7 +1137,7 @@ public class QrCode extends Symbol {
// Process 8-bit byte
int lbyte = (inputData[position + i] & 0xFF);
if ((inputDataType == DataType.GS1) && (lbyte == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (lbyte == '[')) {
lbyte = 0x1d; /* FNC1 */
}
@ -1164,14 +1164,14 @@ public class QrCode extends Symbol {
while (i < short_data_block_length) {
if (!alphanumPercent) {
if ((inputDataType == DataType.GS1) && (inputData[position + i] == '%')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (inputData[position + i] == '%')) {
first = positionOf('%', rhodium);
second = positionOf('%', rhodium);
count = 2;
prod = (first * 45) + second;
i++;
} else {
if ((inputDataType == DataType.GS1) && (inputData[position + i] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (inputData[position + i] == '[')) {
first = positionOf('%', rhodium); /* FNC1 */
} else {
@ -1183,13 +1183,13 @@ public class QrCode extends Symbol {
if (i < short_data_block_length) {
if (inputMode[position + i] == qrMode.ALPHANUM) {
if ((inputDataType == DataType.GS1) && (inputData[position + i] == '%')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (inputData[position + i] == '%')) {
second = positionOf('%', rhodium);
count = 2;
prod = (first * 45) + second;
alphanumPercent = true;
} else {
if ((inputDataType == DataType.GS1) && (inputData[position + i] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (inputData[position + i] == '[')) {
second = positionOf('%', rhodium); /* FNC1 */
} else {
@ -1211,13 +1211,13 @@ public class QrCode extends Symbol {
if (i < short_data_block_length) {
if (inputMode[position + i] == qrMode.ALPHANUM) {
if ((inputDataType == DataType.GS1) && (inputData[position + i] == '%')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (inputData[position + i] == '%')) {
second = positionOf('%', rhodium);
count = 2;
prod = (first * 45) + second;
alphanumPercent = true;
} else {
if ((inputDataType == DataType.GS1) && (inputData[position + i] == '[')) {
if ((inputSymbolDataType == SymbolDataType.GS1) && (inputData[position + i] == '[')) {
second = positionOf('%', rhodium); /* FNC1 */
} else {
@ -2005,4 +2005,17 @@ public class QrCode extends Symbol {
L, M, Q, H
}
public static class Provider implements SymbolProvider<QrCode> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.QRCODE;
}
@Override
public QrCode provide() {
return new QrCode();
}
}
}

View file

@ -9,10 +9,10 @@ import java.util.Locale;
* delivery postcode followed by house number. A check digit is calculated
* and added.
*/
public class RoyalMail4State extends Symbol {
public class RoyalMail4State extends AbstractSymbol {
/* Handles the 4 State barcodes used in the UK by Royal Mail */
private String[] RoyalTable = {
private final String[] royalTable = {
"TTFF", "TDAF", "TDFA", "DTAF", "DTFA", "DDAA", "TADF", "TFTF", "TFDA",
"DATF", "DADA", "DFTA", "TAFD", "TFAD", "TFFT", "DAAD", "DAFT", "DFAT",
"ATDF", "ADTF", "ADDA", "FTTF", "FTDA", "FDTA", "ATFD", "ADAD", "ADFT",
@ -41,7 +41,7 @@ public class RoyalMail4State extends Symbol {
for (i = 0; i < content.length(); i++) {
index = positionOf(content.charAt(i), krSet);
dest.append(RoyalTable[index]);
dest.append(royalTable[index]);
top += (index + 1) % 6;
bottom += ((index / 6) + 1) % 6;
}
@ -56,7 +56,7 @@ public class RoyalMail4State extends Symbol {
column = 5;
}
dest.append(RoyalTable[(6 * row) + column]);
dest.append(royalTable[(6 * row) + column]);
encodeInfo.append("Check Digit: ").append((6 * row) + column).append("\n");
@ -75,7 +75,7 @@ public class RoyalMail4State extends Symbol {
}
@Override
protected void plotSymbol() {
public void plotSymbol() {
int xBlock;
int x, y, w, h;
getRectangles().clear();
@ -109,4 +109,17 @@ public class RoyalMail4State extends Symbol {
symbolWidth = pattern[0].length() * 3;
symbolHeight = 8;
}
public static class Provider implements SymbolProvider<RoyalMail4State> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.ROYALMAIL4STATE;
}
@Override
public RoyalMail4State provide() {
return new RoyalMail4State();
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,5 @@
package org.xbib.graphics.barcode;
public enum SymbolDataType {
UTF8, LATIN1, BINARY, GS1, HIBC, ECI
}

View file

@ -0,0 +1,8 @@
package org.xbib.graphics.barcode;
public interface SymbolProvider<S extends Symbol> {
boolean canProvide(SymbolType type);
S provide();
}

View file

@ -0,0 +1,46 @@
package org.xbib.graphics.barcode;
public enum SymbolType {
AUSTRALIA_POST,
AZTEC_CODE,
AZTEC_RUNE,
CHANNEL_CODE,
CODABAR,
CODABLOCK_F,
CODE25,
CODE39,
CODE39_EXT,
CODE11,
CODE16K,
CODE32,
CODE49,
CODE93,
CODE128,
CODEONE,
COMPOSITE,
DATABAR_14,
DATABAR_EXPANDED,
DATABAR_LIMITED,
DATA_MATRIX,
EAN,
GRID_MATRIX,
JAPAN_POST,
KIX_CODE,
KOREA_POST,
LOG_MARS,
MAXI_CODE,
MICRO_QRCODE,
MSI_PLESSEY,
NVE_18,
PDF417,
PHARMACODE,
PHARMACODE2TRACK,
PHARMAZENTRALNUMMER,
POSTNET,
QRCODE,
ROYALMAIL4STATE,
TELEPEN,
UPC,
USPS_ONE_CODE,
USPS_PACKAGE
}

View file

@ -7,9 +7,9 @@ package org.xbib.graphics.barcode;
* or pairs consisting of a numerical digit followed an X character.
* Telepen Numeric also includes a modulo-127 check digit.
*/
public class Telepen extends Symbol {
public class Telepen extends AbstractSymbol {
public tp_mode mode;
public Mode mode;
private String[] TeleTable = {
"1111111111111111", "1131313111", "33313111", "1111313131",
"3111313111", "11333131", "13133131", "111111313111", "31333111",
@ -42,20 +42,20 @@ public class Telepen extends Symbol {
};
public Telepen() {
mode = tp_mode.NORMAL;
mode = Mode.NORMAL;
}
public void setNormalMode() {
mode = tp_mode.NORMAL;
mode = Mode.NORMAL;
}
public void setNumericMode() {
mode = tp_mode.NUMERIC;
mode = Mode.NUMERIC;
}
@Override
public boolean encode() {
if (mode == tp_mode.NORMAL) {
if (mode == Mode.NORMAL) {
return normal_mode();
} else {
return numeric_mode();
@ -171,7 +171,20 @@ public class Telepen extends Symbol {
return true;
}
public enum tp_mode {
public enum Mode {
NORMAL, NUMERIC
}
public static class Provider implements SymbolProvider<Telepen> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.TELEPEN;
}
@Override
public Telepen provide() {
return new Telepen();
}
}
}

View file

@ -18,7 +18,7 @@ import java.awt.geom.Rectangle2D;
*
* @author <a href="mailto:jakel2006@me.com">Robert Elliott</a>
*/
public class Upc extends Symbol {
public class Upc extends AbstractSymbol {
private boolean useAddOn;
@ -330,7 +330,7 @@ public class Upc extends Symbol {
}
@Override
protected void plotSymbol() {
public void plotSymbol() {
int xBlock;
int x, y, w, h;
boolean black;
@ -442,4 +442,17 @@ public class Upc extends Symbol {
public enum Mode {
UPCA, UPCE
}
public static class Provider implements SymbolProvider<Upc> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.UPC;
}
@Override
public Upc provide() {
return new Upc();
}
}
}

View file

@ -15,13 +15,13 @@ import java.math.BigInteger;
* tracking code, followed by a dash (-), followed by a delivery point
* zip-code which can be 0, 5, 9 or 11 digits in length.
*/
public class UspsOneCode extends Symbol {
public class UspsOneCode extends AbstractSymbol {
/* The following lookup tables were generated using the code in Appendix C */
private int[] byte_array = new int[13];
private final int[] byte_array = new int[13];
private int[] AppxD_I = { /* Appendix D Table 1 - 5 of 13 characters */
private final int[] appxD_I = { /* Appendix D Table 1 - 5 of 13 characters */
0x001F, 0x1F00, 0x002F, 0x1E80, 0x0037, 0x1D80, 0x003B, 0x1B80, 0x003D, 0x1780,
0x003E, 0x0F80, 0x004F, 0x1E40, 0x0057, 0x1D40, 0x005B, 0x1B40, 0x005D, 0x1740,
0x005E, 0x0F40, 0x0067, 0x1CC0, 0x006B, 0x1AC0, 0x006D, 0x16C0, 0x006E, 0x0EC0,
@ -310,7 +310,7 @@ public class UspsOneCode extends Symbol {
for (i = 0; i < 10; i++) {
if (codeword[i] < 1287) {
characters[i] = AppxD_I[codeword[i]];
characters[i] = appxD_I[codeword[i]];
} else {
characters[i] = AppxD_II[codeword[i] - 1287];
}
@ -393,7 +393,7 @@ public class UspsOneCode extends Symbol {
}
@Override
protected void plotSymbol() {
public void plotSymbol() {
int xBlock, shortHeight, longHeight;
double x, y, w, h;
getRectangles().clear();
@ -448,4 +448,17 @@ public class UspsOneCode extends Symbol {
getTexts().add(new TextBox(centerX, baseline, readable.toString()));
}
}
public static class Provider implements SymbolProvider<UspsOneCode> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.USPS_ONE_CODE;
}
@Override
public UspsOneCode provide() {
return new UspsOneCode();
}
}
}

View file

@ -8,7 +8,7 @@ import java.awt.geom.Rectangle2D;
* A linear barcode based on GS1-128. Includes additional data checks.
* Specification at https://ribbs.usps.gov/intelligentmail_package/documents/tech_guides/BarcodePackageIMSpec.pdf
*/
public class UspsPackage extends Symbol {
public class UspsPackage extends AbstractSymbol {
@Override
public boolean encode() {
@ -31,7 +31,7 @@ public class UspsPackage extends Symbol {
Code128 code128 = new Code128();
code128.unsetCc();
code128.setDataType(DataType.GS1);
code128.setDataType(SymbolDataType.GS1);
code128.setContent(content);
if (content.length() > 4) {
@ -66,12 +66,11 @@ public class UspsPackage extends Symbol {
rowHeight = new int[1];
rowHeight[0] = -1;
plotSymbol();
return true;
}
@Override
protected void plotSymbol() {
public void plotSymbol() {
int xBlock;
int x, y, w, h;
boolean black;
@ -111,4 +110,17 @@ public class UspsPackage extends Symbol {
getTexts().add(new TextBox(centerX, getHeight() - 6.0, readable.toString()));
getTexts().add(new TextBox(centerX, 12.0, banner));
}
public static class Provider implements SymbolProvider<UspsPackage> {
@Override
public boolean canProvide(SymbolType type) {
return type == SymbolType.USPS_PACKAGE;
}
@Override
public UspsPackage provide() {
return new UspsPackage();
}
}
}

View file

@ -21,7 +21,7 @@ import java.util.Map;
/**
* Renders symbologies using the Java Graphics API.
*/
public class GraphicsRenderer {
public class BarcodeGraphicsRenderer {
/**
* The graphics to render to.
@ -60,13 +60,13 @@ public class GraphicsRenderer {
* @param antialias if true give anti alias hint
* @param transparentBackground if true background should be transparent
*/
public GraphicsRenderer(Graphics2D g2d,
Rectangle rectangle,
double scalingFactor,
Color background,
Color foreground,
boolean antialias,
boolean transparentBackground) {
public BarcodeGraphicsRenderer(Graphics2D g2d,
Rectangle rectangle,
double scalingFactor,
Color background,
Color foreground,
boolean antialias,
boolean transparentBackground) {
this.g2d = g2d;
this.rectangle = rectangle;
this.scalingFactor = scalingFactor;
@ -90,7 +90,9 @@ public class GraphicsRenderer {
g2d.setBackground(background);
if (!transparentBackground) {
g2d.setColor(background);
g2d.fill(rectangle);
if (rectangle != null) {
g2d.fill(rectangle);
}
g2d.setColor(foreground);
}
for (Rectangle2D.Double rect : symbol.getRectangles()) {

View file

@ -0,0 +1,42 @@
org.xbib.graphics.barcode.AustraliaPost$Provider
org.xbib.graphics.barcode.AztecCode$Provider
org.xbib.graphics.barcode.AztecRune$Provider
org.xbib.graphics.barcode.ChannelCode$Provider
org.xbib.graphics.barcode.Codabar$Provider
org.xbib.graphics.barcode.CodablockF$Provider
org.xbib.graphics.barcode.Code2Of5$Provider
org.xbib.graphics.barcode.Code3Of9$Provider
org.xbib.graphics.barcode.Code3Of9Extended$Provider
org.xbib.graphics.barcode.Code11$Provider
org.xbib.graphics.barcode.Code16k$Provider
org.xbib.graphics.barcode.Code32$Provider
org.xbib.graphics.barcode.Code49$Provider
org.xbib.graphics.barcode.Code93$Provider
org.xbib.graphics.barcode.Code128$Provider
org.xbib.graphics.barcode.CodeOne$Provider
org.xbib.graphics.barcode.Composite$Provider
org.xbib.graphics.barcode.DataBar14$Provider
org.xbib.graphics.barcode.DataBarExpanded$Provider
org.xbib.graphics.barcode.DataBarLimited$Provider
org.xbib.graphics.barcode.DataMatrix$Provider
org.xbib.graphics.barcode.Ean$Provider
org.xbib.graphics.barcode.GridMatrix$Provider
org.xbib.graphics.barcode.JapanPost$Provider
org.xbib.graphics.barcode.KixCode$Provider
org.xbib.graphics.barcode.KoreaPost$Provider
org.xbib.graphics.barcode.Logmars$Provider
org.xbib.graphics.barcode.MaxiCode$Provider
org.xbib.graphics.barcode.MicroQrCode$Provider
org.xbib.graphics.barcode.MsiPlessey$Provider
org.xbib.graphics.barcode.Nve18$Provider
org.xbib.graphics.barcode.Pdf417$Provider
org.xbib.graphics.barcode.Pharmacode$Provider
org.xbib.graphics.barcode.Pharmacode2Track$Provider
org.xbib.graphics.barcode.Pharmazentralnummer$Provider
org.xbib.graphics.barcode.Postnet$Provider
org.xbib.graphics.barcode.QrCode$Provider
org.xbib.graphics.barcode.RoyalMail4State$Provider
org.xbib.graphics.barcode.Telepen$Provider
org.xbib.graphics.barcode.Upc$Provider
org.xbib.graphics.barcode.UspsOneCode$Provider
org.xbib.graphics.barcode.UspsPackage$Provider

View file

@ -24,7 +24,7 @@ import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.runners.Parameterized;
import org.reflections.Reflections;
import org.xbib.graphics.barcode.render.GraphicsRenderer;
import org.xbib.graphics.barcode.render.BarcodeGraphicsRenderer;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontFormatException;
@ -87,7 +87,7 @@ public class SymbolTest {
private static Font DEJA_VU_SANS;
/** The type of symbology being tested. */
private final Class< ? extends Symbol> symbolType;
private final Class< ? extends AbstractSymbol> symbolType;
/** The test configuration properties. */
private final Map< String, String > properties;
@ -121,9 +121,9 @@ public class SymbolTest {
}
String backend = "org.xbib.graphics.barcode";
Reflections reflections = new Reflections(backend);
Set< Class< ? extends Symbol >> symbols = reflections.getSubTypesOf(Symbol.class);
Set< Class< ? extends AbstractSymbol>> symbols = reflections.getSubTypesOf(AbstractSymbol.class);
List< Object[] > data = new ArrayList<>();
for (Class< ? extends Symbol > symbol : symbols) {
for (Class< ? extends AbstractSymbol> symbol : symbols) {
String symbolName = symbol.getSimpleName().toLowerCase();
String dir = "src/test/resources/" + backend.replace('.', '/') + "/" + symbolName;
for (File file : getPropertiesFiles(dir)) {
@ -148,7 +148,7 @@ public class SymbolTest {
* @param pngFile the file containing the expected final rendering of the bar code, if this test verifies successful behavior
* @param errorFile the file containing the expected error message, if this test verifies a failure
*/
public SymbolTest(Class< ? extends Symbol > symbolType,
public SymbolTest(Class< ? extends AbstractSymbol> symbolType,
Map< String, String > properties,
File codewordsFile,
File pngFile,
@ -167,7 +167,7 @@ public class SymbolTest {
*/
@TestTemplate
public void test() throws Exception {
Symbol symbol = symbolType.getDeclaredConstructor().newInstance();
AbstractSymbol symbol = symbolType.getDeclaredConstructor().newInstance();
symbol.setFontName(DEJA_VU_SANS.getFontName());
try {
setProperties(symbol, properties);
@ -189,7 +189,7 @@ public class SymbolTest {
* @throws IOException if there is any I/O error
* @throws ReaderException if ZXing has an issue decoding the barcode image
*/
private void verifySuccess(Symbol symbol) throws IOException, ReaderException {
private void verifySuccess(AbstractSymbol symbol) throws IOException, ReaderException {
if (symbol.errorMsg.length() > 0) {
fail("got error message: " + symbol.errorMsg);
}
@ -242,7 +242,7 @@ public class SymbolTest {
* @param symbol the symbol to be read
* @return a ZXing reader that can read the specified symbol
*/
private static Reader findReader(Symbol symbol) {
private static Reader findReader(AbstractSymbol symbol) {
if (symbol instanceof Code93) {
return new Code93Reader();
} else if (symbol instanceof Code3Of9) {
@ -282,7 +282,7 @@ public class SymbolTest {
* @param symbol the symbol which encoded the content
* @return the barcode content, without the checksum
*/
private static String removeChecksum(String s, Symbol symbol) {
private static String removeChecksum(String s, AbstractSymbol symbol) {
if (symbol instanceof Ean || symbol instanceof Upc) {
return s.substring(0, s.length() - 1);
} else {
@ -298,7 +298,7 @@ public class SymbolTest {
* @param symbol the symbol which encoded the content
* @return the barcode content, without the start/stop characters
*/
private static String removeStartStopChars(String s, Symbol symbol) {
private static String removeStartStopChars(String s, AbstractSymbol symbol) {
if (symbol instanceof Codabar) {
return s.substring(1, s.length() - 1);
} else {
@ -312,7 +312,7 @@ public class SymbolTest {
* @param symbol the symbol to check
* @throws IOException if there is any I/O error
*/
private void verifyError(Symbol symbol) throws IOException {
private void verifyError(AbstractSymbol symbol) throws IOException {
String expectedError = Files.readAllLines(errorFile.toPath(), StandardCharsets.UTF_8).get(0);
assertTrue(symbol.errorMsg.toString().contains(expectedError));
}
@ -323,7 +323,7 @@ public class SymbolTest {
* @param symbol the symbol to generate expectation files for
* @throws IOException if there is any I/O error
*/
private void generateExpectationFiles(Symbol symbol) throws IOException {
private void generateExpectationFiles(AbstractSymbol symbol) throws IOException {
if (symbol.errorMsg != null && symbol.errorMsg.length() > 0) {
generateErrorExpectationFile(symbol);
} else {
@ -338,7 +338,7 @@ public class SymbolTest {
* @param symbol the symbol to generate the error expectation file for
* @throws IOException if there is any I/O error
*/
private void generateErrorExpectationFile(Symbol symbol) throws IOException {
private void generateErrorExpectationFile(AbstractSymbol symbol) throws IOException {
if (!errorFile.exists()) {
PrintWriter writer = new PrintWriter(errorFile);
writer.println(symbol.errorMsg);
@ -352,7 +352,7 @@ public class SymbolTest {
* @param symbol the symbol to generate codewords for
* @throws IOException if there is any I/O error
*/
private void generateCodewordsExpectationFile(Symbol symbol) throws IOException {
private void generateCodewordsExpectationFile(AbstractSymbol symbol) throws IOException {
//if (!codewordsFile.exists()) {
PrintWriter writer = new PrintWriter(codewordsFile);
try {
@ -375,7 +375,7 @@ public class SymbolTest {
* @param symbol the symbol to draw
* @throws IOException if there is any I/O error
*/
private void generatePngExpectationFile(Symbol symbol) throws IOException {
private void generatePngExpectationFile(AbstractSymbol symbol) throws IOException {
BufferedImage img = draw(symbol, 10.0d);
if (img != null) {
ImageIO.write(img, "png", pngFile);
@ -403,14 +403,14 @@ public class SymbolTest {
* @param symbol the symbol to draw
* @return the resultant image
*/
private static BufferedImage draw(Symbol symbol, double scalingFactor) {
private static BufferedImage draw(AbstractSymbol symbol, double scalingFactor) {
int width = (int) (symbol.getWidth() * scalingFactor);
int height = (int) (symbol.getHeight() * scalingFactor);
if (width > 0 && height > 0) {
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
Rectangle rectangle = new Rectangle(0, 0, img.getWidth(), img.getHeight());
Graphics2D g2d = img.createGraphics();
GraphicsRenderer renderer = new GraphicsRenderer(g2d, rectangle,
BarcodeGraphicsRenderer renderer = new BarcodeGraphicsRenderer(g2d, rectangle,
scalingFactor, Color.WHITE, Color.BLACK, true, false);
renderer.render(symbol);
g2d.dispose();
@ -427,7 +427,7 @@ public class SymbolTest {
* @param properties the attribute names and values to set
* @throws ReflectiveOperationException if there is any reflection error
*/
private static void setProperties(Symbol symbol, Map< String, String > properties) throws ReflectiveOperationException {
private static void setProperties(AbstractSymbol symbol, Map< String, String > properties) throws ReflectiveOperationException {
for (Map.Entry< String, String > entry : properties.entrySet()) {
String name = entry.getKey();
String value = entry.getValue();

View file

@ -3,7 +3,7 @@ package org.xbib.graphics.barcode.output;
import org.junit.jupiter.api.Test;
import org.xbib.graphics.barcode.Code3Of9;
import org.xbib.graphics.barcode.HumanReadableLocation;
import org.xbib.graphics.barcode.render.GraphicsRenderer;
import org.xbib.graphics.barcode.render.BarcodeGraphicsRenderer;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
@ -26,7 +26,7 @@ public class Code39Test {
int width = (int) (code3Of9.getWidth() * scalingFactor);
int height = (int) (code3Of9.getHeight() * scalingFactor);
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
GraphicsRenderer renderer = createRenderer(bufferedImage, scalingFactor);
BarcodeGraphicsRenderer renderer = createRenderer(bufferedImage, scalingFactor);
renderer.render(code3Of9);
renderer.close();
OutputStream outputStream = Files.newOutputStream(Paths.get("build/barcode1.png"));
@ -42,7 +42,7 @@ public class Code39Test {
//code3Of9.setContent("20180123456");
code3Of9.setContent("11111111111");
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
GraphicsRenderer renderer = createRenderer(bufferedImage, 3.0d);
BarcodeGraphicsRenderer renderer = createRenderer(bufferedImage, 3.0d);
renderer.render(code3Of9);
renderer.close();
OutputStream outputStream = Files.newOutputStream(Paths.get("build/barcode2.png"));
@ -50,9 +50,9 @@ public class Code39Test {
outputStream.close();
}
private GraphicsRenderer createRenderer(BufferedImage bufferedImage, double scalingFactor) {
private BarcodeGraphicsRenderer createRenderer(BufferedImage bufferedImage, double scalingFactor) {
Graphics2D g2d = bufferedImage.createGraphics();
Rectangle rectangle = new Rectangle(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight());
return new GraphicsRenderer(g2d, rectangle, scalingFactor, Color.WHITE, Color.BLACK, false, false);
return new BarcodeGraphicsRenderer(g2d, rectangle, scalingFactor, Color.WHITE, Color.BLACK, false, false);
}
}

View file

@ -4,10 +4,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.xbib.graphics.barcode.Code93;
import org.xbib.graphics.barcode.render.GraphicsRenderer;
import org.xbib.graphics.barcode.render.BarcodeGraphicsRenderer;
import org.xbib.graphics.barcode.MaxiCode;
import org.xbib.graphics.barcode.Symbol;
import org.xbib.graphics.barcode.AbstractSymbol;
import org.xbib.graphics.io.vector.eps.EPSGraphics2D;
import java.awt.Color;
import java.awt.Font;
@ -22,6 +24,7 @@ import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Locale;
@DisabledOnOs(OS.MAC)
public class EPSRendererTest {
private Locale originalDefaultLocale;
@ -83,7 +86,7 @@ public class EPSRendererTest {
test(maxicode, 5, Color.WHITE, Color.BLACK, 5, "maxicode-basic.eps");
}
private void test(Symbol symbol,
private void test(AbstractSymbol symbol,
double magnification,
Color paper,
Color ink,
@ -96,10 +99,10 @@ public class EPSRendererTest {
Rectangle rectangle = new Rectangle(0, 0, width, height);
EPSGraphics2D epsGraphics2D = new EPSGraphics2D(rectangle);
epsGraphics2D.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 12));
GraphicsRenderer graphicsRenderer = new GraphicsRenderer(epsGraphics2D, rectangle,
BarcodeGraphicsRenderer barcodeGraphicsRenderer = new BarcodeGraphicsRenderer(epsGraphics2D, rectangle,
magnification, paper, ink, false, false);
graphicsRenderer.render(symbol);
graphicsRenderer.close();
barcodeGraphicsRenderer.render(symbol);
barcodeGraphicsRenderer.close();
byte[] actualBytes = epsGraphics2D.getBytes();
String actual = new String(actualBytes, StandardCharsets.UTF_8);
try (BufferedWriter bufferedWriter = Files.newBufferedWriter(Paths.get("build/" + expectationFile))) {

View file

@ -4,10 +4,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.xbib.graphics.barcode.Code93;
import org.xbib.graphics.barcode.MaxiCode;
import org.xbib.graphics.barcode.Symbol;
import org.xbib.graphics.barcode.render.GraphicsRenderer;
import org.xbib.graphics.barcode.AbstractSymbol;
import org.xbib.graphics.barcode.render.BarcodeGraphicsRenderer;
import org.xbib.graphics.io.vector.pdf.PDFGraphics2D;
import java.awt.Color;
import java.awt.Font;
@ -22,6 +24,7 @@ import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Locale;
@DisabledOnOs(OS.MAC)
public class PDFRendererTest {
private Locale originalDefaultLocale;
@ -83,7 +86,7 @@ public class PDFRendererTest {
test(maxicode, 5, Color.WHITE, Color.BLACK, 5, "maxicode-basic.pdf");
}
private void test(Symbol symbol,
private void test(AbstractSymbol symbol,
double magnification,
Color paper,
Color ink,
@ -96,10 +99,10 @@ public class PDFRendererTest {
Rectangle rectangle = new Rectangle(0, 0, width, height);
PDFGraphics2D pdfGraphics2D = new PDFGraphics2D(rectangle);
pdfGraphics2D.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 12));
GraphicsRenderer graphicsRenderer = new GraphicsRenderer(pdfGraphics2D,
BarcodeGraphicsRenderer barcodeGraphicsRenderer = new BarcodeGraphicsRenderer(pdfGraphics2D,
rectangle, magnification, paper, ink, false, false);
graphicsRenderer.render(symbol);
graphicsRenderer.close();
barcodeGraphicsRenderer.render(symbol);
barcodeGraphicsRenderer.close();
byte[] actualBytes = pdfGraphics2D.getBytes();
String actual = new String(actualBytes, StandardCharsets.UTF_8);
try (BufferedWriter bufferedWriter = Files.newBufferedWriter(Paths.get("build/" + expectationFile))) {

View file

@ -4,10 +4,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.xbib.graphics.barcode.Code93;
import org.xbib.graphics.barcode.MaxiCode;
import org.xbib.graphics.barcode.Symbol;
import org.xbib.graphics.barcode.render.GraphicsRenderer;
import org.xbib.graphics.barcode.AbstractSymbol;
import org.xbib.graphics.barcode.render.BarcodeGraphicsRenderer;
import org.xbib.graphics.io.vector.svg.SVGGraphics2D;
import java.awt.Color;
import java.awt.Font;
@ -22,6 +24,7 @@ import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Locale;
@DisabledOnOs(OS.MAC)
public class SvgRendererTest {
private Locale originalDefaultLocale;
@ -83,7 +86,7 @@ public class SvgRendererTest {
test(maxicode, 1.0, Color.WHITE, Color.BLACK, 5, "maxicode-basic.svg");
}
private void test(Symbol symbol,
private void test(AbstractSymbol symbol,
double magnification,
Color paper,
Color ink,
@ -96,10 +99,10 @@ public class SvgRendererTest {
Rectangle rectangle = new Rectangle(0, 0, width, height);
SVGGraphics2D svgGraphics2D = new SVGGraphics2D(rectangle);
svgGraphics2D.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 12));
GraphicsRenderer graphicsRenderer = new GraphicsRenderer(svgGraphics2D,
BarcodeGraphicsRenderer barcodeGraphicsRenderer = new BarcodeGraphicsRenderer(svgGraphics2D,
rectangle, magnification, paper, ink, false, false);
graphicsRenderer.render(symbol);
graphicsRenderer.close();
barcodeGraphicsRenderer.render(symbol);
barcodeGraphicsRenderer.close();
byte[] actualBytes = svgGraphics2D.getBytes();
String actual = new String(actualBytes, StandardCharsets.UTF_8);
try (BufferedWriter bufferedWriter = Files.newBufferedWriter(Paths.get("build/" + expectationFile))) {

View file

@ -1,5 +1,6 @@
module org.xbib.graphics.ghostscript {
exports org.xbib.graphics.ghostscript;
requires com.sun.jna;
requires java.logging;
requires transitive java.desktop;
requires transitive org.apache.pdfbox;

View file

@ -8,7 +8,6 @@ import org.xbib.graphics.ghostscript.internal.GhostscriptLibraryLoader;
import org.xbib.graphics.ghostscript.internal.LoggingOutputStream;
import org.xbib.graphics.ghostscript.internal.NullOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -32,7 +31,7 @@ public class Ghostscript {
private static final Logger logger = Logger.getLogger(Ghostscript.class.getName());
public static final String ENCODING_PARAMETER = "org.xbib.graphics.gs.encoding";
public static final String ENCODING_PARAMETER = "org.xbib.graphics.ghostscript.encoding";
private static Ghostscript instance;
@ -46,26 +45,21 @@ public class Ghostscript {
private static OutputStream stdErr;
private static String tmpDir;
private static Path tmpDir;
private Ghostscript() {
}
public static synchronized Ghostscript getInstance() throws IOException {
if (instance == null) {
tmpDir = System.getenv("TMPDIR");
if (tmpDir != null) {
if (new File(tmpDir).mkdirs()) {
logger.info("tmp dir " + tmpDir + " created");
}
}
prepareTmp();
instance = new Ghostscript();
libraryInstance = getGhostscriptLibrary();
nativeInstanceByRef = getNativeInstanceByRef();
//stdOut = new LoggingOutputStream(logger);
//stdErr = new LoggingOutputStream(logger);
//instance.setStdOut(stdOut);
//instance.setStdErr(stdErr);
stdOut = new LoggingOutputStream(logger);
stdErr = new LoggingOutputStream(logger);
instance.setStdOut(stdOut);
instance.setStdErr(stdErr);
}
return instance;
}
@ -96,19 +90,16 @@ public class Ghostscript {
* @throws IOException if delete of instance fails
*/
public static synchronized void deleteInstance() throws IOException {
if (libraryInstance != null) {
//libraryInstance.gsapi_exit(nativeInstanceByRef.getValue());
libraryInstance.gsapi_delete_instance(nativeInstanceByRef.getValue());
libraryInstance = null;
}
if (nativeInstanceByRef != null) {
nativeInstanceByRef = null;
}
if (instance != null) {
if (tmpDir != null) {
deleteGs(tmpDir);
if (libraryInstance != null) {
libraryInstance.gsapi_delete_instance(nativeInstanceByRef.getValue());
libraryInstance = null;
}
if (nativeInstanceByRef != null) {
nativeInstanceByRef = null;
}
instance = null;
deleteTmp();
}
}
@ -118,6 +109,7 @@ public class Ghostscript {
* @return the Ghostscript revision data.
*/
public static GhostscriptRevision getRevision() {
getGhostscriptLibrary();
GhostscriptLibrary.gsapi_revision_s revision = new GhostscriptLibrary.gsapi_revision_s();
libraryInstance.gsapi_revision(revision, revision.size());
GhostscriptRevision result = new GhostscriptRevision();
@ -192,9 +184,8 @@ public class Ghostscript {
* @throws IOException if initialize fails
*/
public void initialize(String[] args) throws IOException {
if (libraryInstance == null || nativeInstanceByRef == null) {
return;
}
getGhostscriptLibrary();
getNativeInstanceByRef();
int result;
GhostscriptLibrary.stdin_fn stdinCallback = null;
if (getStdIn() != null) {
@ -265,12 +256,10 @@ public class Ghostscript {
* @throws IOException if exit fails
*/
public void exit() throws IOException {
if (libraryInstance == null || nativeInstanceByRef == null) {
return;
}
getGhostscriptLibrary();
getNativeInstanceByRef();
Pointer pointer = nativeInstanceByRef.getValue();
if (pointer != null) {
logger.info("gsapi_exit " + pointer);
int result = libraryInstance.gsapi_exit(pointer);
if (result != 0) {
throw new IOException("can not exit Ghostscript interpreter, error code " + result);
@ -286,9 +275,8 @@ public class Ghostscript {
* @throws IOException if run fails
*/
public void runString(String string) throws IOException {
if (libraryInstance == null || nativeInstanceByRef == null) {
return;
}
getGhostscriptLibrary();
getNativeInstanceByRef();
IntByReference exitCode = new IntByReference();
libraryInstance.gsapi_run_string_begin(nativeInstanceByRef.getValue(), 0, exitCode);
if (exitCode.getValue() != 0) {
@ -320,9 +308,8 @@ public class Ghostscript {
* @throws IOException if run of file fails
*/
public void runFile(String fileName) throws IOException {
if (libraryInstance == null || nativeInstanceByRef == null) {
return;
}
getGhostscriptLibrary();
getNativeInstanceByRef();
IntByReference exitCode = new IntByReference();
libraryInstance.gsapi_run_file(nativeInstanceByRef.getValue(), fileName, 0, exitCode);
if (exitCode.getValue() != 0) {
@ -330,25 +317,47 @@ public class Ghostscript {
}
}
private static void deleteGs(String path) throws IOException {
logger.info("delete gs_* in " + path);
private static void prepareTmp() throws IOException {
String tmp = System.getenv("TMPDIR"); // the variable that ghostscript uses
if (tmp == null) {
tmp = System.getenv("TEMP");
}
if (tmp == null) {
throw new IllegalStateException("no TEMP/TMPDIR environment set for ghostscript");
}
tmpDir = Paths.get(tmp);
deleteTmp();
Files.createDirectories(tmpDir);
}
private static void deleteTmp() throws IOException {
if (tmpDir == null) {
return;
}
if (!Files.exists(tmpDir)) {
return;
}
try {
Files.walkFileTree(Paths.get(path), new SimpleFileVisitor<>() {
Files.walkFileTree(tmpDir, new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (file.startsWith("gs_")) {
Files.delete(file);
}
logger.info("deleting " + file);
Files.deleteIfExists(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
logger.info("deleting " + dir);
Files.deleteIfExists(dir);
return FileVisitResult.CONTINUE;
}
});
} catch (NoSuchFileException e) {
logger.log(Level.WARNING, e.getMessage(), e);
} finally {
logger.info("deleting " + tmpDir);
Files.deleteIfExists(tmpDir);
}
}
}

View file

@ -5,11 +5,15 @@ import org.xbib.graphics.ghostscript.internal.LoggingOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.LinkedList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
public class PDFConverter {
@ -68,6 +72,8 @@ public class PDFConverter {
*/
private final PaperSize paperSize;
private final Path tmpPath;
public PDFConverter() {
this(OPTION_AUTOROTATEPAGES_OFF, OPTION_PROCESSCOLORMODEL_RGB,
OPTION_PDFSETTINGS_PRINTER, "1.4", false, PaperSize.A4);
@ -80,10 +86,11 @@ public class PDFConverter {
boolean pdfx, PaperSize paperSize) {
this.autoRotatePages = autoRotatePages;
this.processColorModel = processColorModel;
this. pdfsettings = pdfsettings;
this.pdfsettings = pdfsettings;
this.compatibilityLevel = compatibilityLevel;
this.pdfx = pdfx;
this.paperSize = paperSize;
this.tmpPath = Paths.get("/var/tmp/" + this);
}
/**
@ -98,6 +105,8 @@ public class PDFConverter {
if (outputStream == null) {
return;
}
prepare(tmpPath);
Path output = Files.createTempFile(tmpPath, "pdf", "pdf");
Ghostscript gs = Ghostscript.getInstance();
List<String> gsArgs = new LinkedList<>();
gsArgs.add("-ps2pdf");
@ -151,7 +160,6 @@ public class PDFConverter {
gsArgs.add("-dDEVICEWIDTHPOINTS=" + paperSize.getWidth());
gsArgs.add("-dDEVICEHEIGHTPOINTS=" + paperSize.getHeight());
gsArgs.add("-sDEVICE=pdfwrite");
Path output = Files.createTempFile("pdf", "pdf");
gsArgs.add("-sOutputFile=" + output.toAbsolutePath().toString());
//gsArgs.add("-q");
gsArgs.add("-f");
@ -164,7 +172,39 @@ public class PDFConverter {
Files.copy(output.toAbsolutePath(), outputStream);
} finally {
Ghostscript.deleteInstance();
Files.delete(output);
delete(tmpPath);
}
}
private static void prepare(Path path) throws IOException {
Files.createDirectories(path);
}
private static void delete(Path path) throws IOException {
if (path == null) {
return;
}
if (!Files.exists(path)) {
return;
}
try {
Files.walkFileTree(path.toAbsolutePath(), new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.deleteIfExists(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.deleteIfExists(dir);
return FileVisitResult.CONTINUE;
}
});
} catch (Exception e) {
logger.log(Level.WARNING, e.getMessage(), e);
} finally {
Files.deleteIfExists(path);
}
}
}

View file

@ -24,6 +24,7 @@ import java.io.OutputStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
@ -52,8 +53,10 @@ public class PDFRasterizer implements Closeable {
private final Map<String, ImageReader> imageReaders;
private final Path tmpPath;
public PDFRasterizer(String subject) {
this("org.xbib.graphics.gs/1.0.8", "Jörg Prante <prante@hbz-nrw.de>", subject);
this("org.xbib.graphics.ghostscript/4.0.1", "Jörg Prante", subject);
}
public PDFRasterizer(String creator, String author, String subject) {
@ -61,6 +64,7 @@ public class PDFRasterizer implements Closeable {
this.author = author;
this.subject = subject;
this.imageReaders = createImageReaders();
this.tmpPath = Paths.get("/var/tmp/" + this);
}
@Override
@ -79,7 +83,8 @@ public class PDFRasterizer implements Closeable {
if (Files.size(source) == 0) {
throw new IOException("empty file at " + source.toString());
}
Path tmp = Files.createTempDirectory("pdf-rasterize");
prepare(tmpPath);
Path tmp = Files.createTempDirectory(tmpPath, "pdf-rasterize");
if (!Files.isWritable(tmp)) {
throw new IOException("unable to write to " + tmp.toString());
}
@ -90,7 +95,7 @@ public class PDFRasterizer implements Closeable {
scalePDF(tmpTarget, target);
logger.info("convert source=" + source + " done");
} finally {
delete(tmp);
delete(tmpPath);
}
}
@ -102,16 +107,17 @@ public class PDFRasterizer implements Closeable {
if (!Files.isReadable(source.toAbsolutePath())) {
throw new IOException("unable to read " + source.toString());
}
Path tmp = Files.createTempDirectory("pdf-rasterize");
prepare(tmpPath);
Path tmp = Files.createTempDirectory(tmpPath, "pdf-rasterize");
try {
pdfToGrayScreenImage(source.toAbsolutePath(), tmp);
Path tmpTarget = tmp.resolve(target.getFileName());
mergeImagesToPDF(tmp, tmpTarget);
//toPDFA(tmpTarget, target);
scalePDF(tmpTarget, target);
} finally {
delete(tmp);
logger.info("convert source=" + source.toAbsolutePath() + " done");
} finally {
delete(tmpPath);
}
}
@ -123,8 +129,8 @@ public class PDFRasterizer implements Closeable {
if (!Files.isReadable(source.toAbsolutePath())) {
throw new IOException("unable to read " + source.toString());
}
Ghostscript gs = Ghostscript.getInstance();
try {
Ghostscript gs = Ghostscript.getInstance();
List<String> gsArgs = new LinkedList<>();
gsArgs.add("-dNOPAUSE");
gsArgs.add("-dBATCH");
@ -144,9 +150,9 @@ public class PDFRasterizer implements Closeable {
gs.setStdErr(new LoggingOutputStream(logger));
gs.initialize(gsArgs.toArray(new String[gsArgs.size()]));
gs.exit();
logger.info("pdfToImage done");
} finally {
Ghostscript.deleteInstance();
logger.info("pdfToImage done");
}
}
@ -155,8 +161,8 @@ public class PDFRasterizer implements Closeable {
String prefix,
String pageRange) throws IOException {
logger.info("pdfToImage source=" + sourceFile + " target=" + targetDir + " started");
Ghostscript gs = Ghostscript.getInstance();
try {
Ghostscript gs = Ghostscript.getInstance();
List<String> gsArgs = new LinkedList<>();
gsArgs.add("-dNOPAUSE");
gsArgs.add("-dBATCH");
@ -186,9 +192,9 @@ public class PDFRasterizer implements Closeable {
gs.setStdErr(new LoggingOutputStream(logger));
gs.initialize(gsArgs.toArray(new String[gsArgs.size()]));
gs.exit();
logger.info("pdfToImage done");
} finally {
Ghostscript.deleteInstance();
logger.info("pdfToImage done");
}
}
@ -266,8 +272,8 @@ public class PDFRasterizer implements Closeable {
public synchronized void scalePDF(Path sourceFile,
Path targetFile) throws IOException {
logger.info("scalePDF: source = " + sourceFile + " target = " + targetFile + " starting");
Ghostscript gs = Ghostscript.getInstance();
try {
Ghostscript gs = Ghostscript.getInstance();
List<String> gsArgs = new LinkedList<>();
gsArgs.add("-dNOPAUSE");
gsArgs.add("-dBATCH");
@ -285,18 +291,19 @@ public class PDFRasterizer implements Closeable {
logger.info(gsArgs.toString());
gs.initialize(gsArgs.toArray(new String[gsArgs.size()]));
gs.exit();
logger.info("scalePDF: source = " + sourceFile + " target = " + targetFile + " done");
} finally {
Ghostscript.deleteInstance();
logger.info("scalePDF: source = " + sourceFile + " target = " + targetFile + " done");
}
}
public void toPDFA(Path source, Path target) throws IOException {
Path iccPath = Files.createTempFile("srgb", ".icc");
Path pdfapsPathTmp = Files.createTempFile("PDFA_def", ".tmp");
Path pdfapsPath = Files.createTempFile("PDFA_def", ".ps");
prepare(tmpPath);
Path iccPath = Files.createTempFile(tmpPath, "srgb", ".icc");
Path pdfapsPathTmp = Files.createTempFile(tmpPath, "PDFA_def", ".tmp");
Path pdfapsPath = Files.createTempFile(tmpPath, "PDFA_def", ".ps");
Ghostscript gs = Ghostscript.getInstance();
try {
Ghostscript gs = Ghostscript.getInstance();
Files.copy(getClass().getResourceAsStream("/iccprofiles/srgb.icc"),
iccPath, StandardCopyOption.REPLACE_EXISTING);
Files.copy(getClass().getResourceAsStream("/lib/PDFA_def.ps"),
@ -434,6 +441,10 @@ public class PDFRasterizer implements Closeable {
return pos >= 0 ? filename.substring(pos + 1).toLowerCase(Locale.ROOT) : null;
}
private static void prepare(Path path) throws IOException {
Files.createDirectories(path);
}
private static void delete(Path path) throws IOException {
if (path == null) {
return;
@ -441,7 +452,6 @@ public class PDFRasterizer implements Closeable {
if (!Files.exists(path)) {
return;
}
logger.info("delete " + path);
try {
Files.walkFileTree(path.toAbsolutePath(), new SimpleFileVisitor<>() {
@Override

View file

@ -1,5 +1,7 @@
package org.xbib.graphics.ghostscript.internal;
import static com.sun.jna.Platform.LINUX;
import static com.sun.jna.Platform.MAC;
import com.sun.jna.Function;
import com.sun.jna.Library;
import com.sun.jna.Native;
@ -14,20 +16,40 @@ public class GhostscriptLibraryLoader {
private static final Logger logger = Logger.getLogger(GhostscriptLibraryLoader.class.getName());
private static final String[] LIBNAMES = {
"libgs.so.9.25", // RHEL 8
"libgs.9.25.dylib", // macOS
"gs.9.25" // other
private static final String[] LINUX_LIBNAMES = {
"gs.so.9.27",
"gs.9.27",
"gs.so.9.25",
"gs.9.25",
"gs"
};
private static final String[] MAC_LIBNAMES = {
"libgs.9.25.dylib",
"libgs.9.25",
"gs.9.25",
"libgs.dylib",
"libgs",
"gs",
};
public static GhostscriptLibrary loadLibrary() {
Map<String, Object> options = new HashMap<>();
options.put(Library.OPTION_CALLING_CONVENTION, Function.C_CONVENTION);
String[] LIBNAMES = {};
switch (Platform.getOSType()) {
case LINUX:
LIBNAMES = LINUX_LIBNAMES;
break;
case MAC:
LIBNAMES = MAC_LIBNAMES;
break;
}
for (String libname : LIBNAMES) {
try {
return Native.load(libname, GhostscriptLibrary.class, options);
} catch (Error e) {
logger.log(Level.WARNING, "library " + libname + " not found");
logger.log(Level.WARNING, "library " + libname + " not found", e);
}
}
return null;

View file

@ -1,5 +1,6 @@
package org.xbib.graphics.ghostscript.test;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@ -7,13 +8,11 @@ import org.xbib.graphics.ghostscript.Ghostscript;
import org.xbib.graphics.ghostscript.GhostscriptRevision;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
public class GhostscriptTest {
@ -27,6 +26,11 @@ public class GhostscriptTest {
gs = Ghostscript.getInstance();
}
@AfterAll
public static void down() throws IOException {
Ghostscript.deleteInstance();
}
@Test
public void testGetRevision() {
GhostscriptRevision revision = Ghostscript.getRevision();
@ -76,24 +80,17 @@ public class GhostscriptTest {
public void testStdOut() throws IOException {
InputStream is = new ByteArrayInputStream("devicenames ==\n".getBytes());
gs.setStdIn(is);
ByteArrayOutputStream os = new ByteArrayOutputStream();
gs.setStdOut(os);
String[] args = { "-dNODISPLAY", "-sOutputFile=%stdout", "-f", "-"};
gs.initialize(args);
gs.exit();
assertTrue(os.toString().length() > 0);
os.close();
is.close();
}
@Test
public void testStdErr() throws IOException {
ByteArrayOutputStream os = null;
try {
InputStream is = new ByteArrayInputStream("stupid\n".getBytes());
gs.setStdIn(is);
os = new ByteArrayOutputStream();
gs.setStdErr(os);
String[] args = { "-dNODISPLAY", "-sOutputFile=%stdout", "-f", "-"};
gs.initialize(args);
gs.exit();
@ -102,14 +99,6 @@ public class GhostscriptTest {
if (!e.getMessage().contains("error code -100")) {
fail(e.getMessage());
}
} finally {
try {
assert os != null;
assertTrue(os.toString().length() > 0);
os.close();
} catch (IOException e2) {
fail(e2.getMessage());
}
}
}
}

View file

@ -0,0 +1,8 @@
handlers=java.util.logging.ConsoleHandler,java.util.logging.FileHandler
.level=INFO
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %4$-7s [%3$s] %5$s %6$s%n
java.util.logging.ConsoleHandler.level=INFO
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.FileHandler.level=INFO
java.util.logging.FileHandler.pattern=build/test.log
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter

View file

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -1,20 +1,22 @@
package org.xbib.graphics.pdfbox.groovy
import org.xbib.graphics.barcode.SymbolType
class Barcode extends BaseNode {
Integer x = 0
Integer y = 0
Integer width = 0
Integer width
Integer height = 0
Integer height
String value
BarcodeType type
SymbolType symbolType
void setType(String type) {
this.type = Enum.valueOf(BarcodeType, type.toUpperCase())
this.symbolType = Enum.valueOf(SymbolType, type.toUpperCase())
}
}

View file

@ -4,8 +4,10 @@ import groovy.transform.AutoClone
@AutoClone
class Color {
String hex = '000000'
def rgb = [0, 0, 0]
def rgb = [0f, 0f, 0f]
void setColor(String value) {
if (value.startsWith('#')) {

View file

@ -74,13 +74,8 @@ class PdfDocument implements Closeable {
papersize = PDRectangle.A4
break
}
switch (document.orientation) {
case 'landscape':
if (document.orientation == 'landscape') {
papersize = swapOrientation(papersize)
break;
case 'portrait':
default:
break
}
document.width = papersize.width as int
document.height = papersize.height as int

View file

@ -4,9 +4,16 @@ import groovy.transform.InheritConstructors
import groovy.util.logging.Log4j2
import groovy.xml.MarkupBuilder
import org.apache.pdfbox.pdmodel.common.PDMetadata
import org.xbib.graphics.pdfbox.groovy.*
import org.xbib.graphics.pdfbox.groovy.Barcode
import org.xbib.graphics.pdfbox.groovy.Cell
import org.xbib.graphics.pdfbox.groovy.Document
import org.xbib.graphics.pdfbox.groovy.HeaderFooterOptions
import org.xbib.graphics.pdfbox.groovy.Image
import org.xbib.graphics.pdfbox.groovy.Line
import org.xbib.graphics.pdfbox.groovy.PageBreak
import org.xbib.graphics.pdfbox.groovy.Row
import org.xbib.graphics.pdfbox.groovy.Table
import org.xbib.graphics.pdfbox.groovy.TextBlock
import org.xbib.graphics.pdfbox.groovy.render.ParagraphRenderer
import org.xbib.graphics.pdfbox.groovy.render.TableRenderer

View file

@ -2,7 +2,7 @@ package org.xbib.graphics.pdfbox.groovy.builder
import org.apache.pdfbox.pdmodel.PDPageContentStream
import org.xbib.graphics.barcode.HumanReadableLocation
import org.xbib.graphics.barcode.Symbol
import org.xbib.graphics.barcode.AbstractSymbol
import org.xbib.graphics.barcode.util.Hexagon
import org.xbib.graphics.barcode.util.TextBox
@ -25,7 +25,7 @@ class PdfboxRenderer {
this.scalingFactor = scalingfactor
}
void render(Symbol symbol) throws IOException {
void render(AbstractSymbol symbol) throws IOException {
Integer marginX = (symbol.getQuietZoneHorizontal() * scalingFactor) as Integer
Integer marginY = (symbol.getQuietZoneVertical() * scalingFactor) as Integer
// rectangles

View file

@ -1,18 +1,17 @@
package org.xbib.graphics.pdfbox.groovy.render
import groovy.util.logging.Log4j2
import org.apache.pdfbox.pdmodel.PDDocument
import org.apache.pdfbox.pdmodel.PDPageContentStream
import org.apache.pdfbox.pdmodel.PDResources
import org.apache.pdfbox.pdmodel.common.PDRectangle
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject
import org.apache.pdfbox.pdmodel.graphics.image.JPEGFactory
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream
import org.xbib.graphics.barcode.Code3Of9
import org.apache.pdfbox.util.Matrix
import org.xbib.graphics.barcode.HumanReadableLocation
import org.xbib.graphics.barcode.render.GraphicsRenderer
import org.xbib.graphics.barcode.Symbol
import org.xbib.graphics.barcode.SymbolProvider
import org.xbib.graphics.barcode.SymbolType
import org.xbib.graphics.barcode.render.BarcodeGraphicsRenderer
import org.xbib.graphics.pdfbox.PdfBoxGraphics2D
import org.xbib.graphics.pdfbox.groovy.*
import org.xbib.graphics.pdfbox.groovy.builder.PdfDocument
@ -22,7 +21,6 @@ import org.xbib.graphics.pdfbox.groovy.render.element.LineElement
import org.xbib.graphics.pdfbox.groovy.render.element.TextElement
import javax.imageio.ImageIO
import java.awt.Rectangle
import java.awt.image.BufferedImage
@Log4j2
@ -170,15 +168,16 @@ class ParagraphRenderer implements Renderable {
}
private void renderTextElement(TextElement element) {
Text text = element.node
PDPageContentStream contentStream = pdfDocument.contentStream
contentStream.beginText()
contentStream.newLineAtOffset(pdfDocument.x as float, pdfDocument.translatedY as float)
Text text = element.node
def color = text.font.color.rgb
contentStream.setNonStrokingColor(color[0], color[1], color[2])
contentStream.setFont(element.pdfFont, text.font.size)
// remove control chars
String string = element.text.replaceAll("\\p{C}","")
contentStream.showText(string) // remove control chars
contentStream.showText(string)
contentStream.endText()
}
@ -199,46 +198,58 @@ class ParagraphRenderer implements Renderable {
Image image = element.node
ImageType imageType = element.node.type
if (imageType) {
PDPageContentStream contentStream = pdfDocument.contentStream
InputStream inputStream = new ByteArrayInputStream(element.node.data)
// TODO add TwelveMonkeys
BufferedImage bufferedImage = ImageIO.read(inputStream)
inputStream.close()
BigDecimal x = pdfDocument.x + image.x
BigDecimal y = pdfDocument.translateY(pdfDocument.y + image.y)
int width = element.node.width
int height = element.node.height
//int width = image.width
//int height = image.height
PDImageXObject img = imageType == ImageType.JPG ?
JPEGFactory.createFromImage(pdfDocument.pdDocument, bufferedImage) :
LosslessFactory.createFromImage(pdfDocument.pdDocument, bufferedImage)
pdfDocument.contentStream.drawImage(img, x as float, y as float, width, height)
inputStream.close()
Matrix matrix = new Matrix()
matrix.translate(x, y)
contentStream.saveGraphicsState()
contentStream.transform(matrix)
contentStream.drawImage(img, 0f, 0f, image.width, image.height)
contentStream.restoreGraphicsState()
}
}
private void renderBarcodeElement(BarcodeElement element) {
switch (element.node.getType()) {
case BarcodeType.CODE39:
float x = pdfDocument.x + element.node.x
float y = pdfDocument.translateY(pdfDocument.y + element.node.y)
Code3Of9 code3Of9 = new Code3Of9()
code3Of9.setContent(element.node.value)
code3Of9.setBarHeight(element.node.height)
code3Of9.setHumanReadableLocation(HumanReadableLocation.NONE)
PDFormXObject formXObject = createXObject(pdfDocument.pdDocument, x, y)
PdfBoxGraphics2D g2d = new PdfBoxGraphics2D(pdfDocument.pdDocument, formXObject, pdfDocument.contentStream, null)
Rectangle rectangle = new Rectangle(0, 0, x as int, y as int)
GraphicsRenderer graphicsRenderer =
new GraphicsRenderer(g2d, rectangle, 1.0d, java.awt.Color.WHITE, java.awt.Color.BLACK, false, false);
graphicsRenderer.render(code3Of9);
graphicsRenderer.close();
break
Barcode barcode = element.node
PDPageContentStream contentStream = pdfDocument.contentStream
Symbol symbol = create(barcode.symbolType)
symbol.setContent(barcode.value)
symbol.setBarHeight(barcode.height)
symbol.setHumanReadableLocation(HumanReadableLocation.BOTTOM)
float x = pdfDocument.x + barcode.x
float y = pdfDocument.translateY(pdfDocument.y + barcode.y)
float width = barcode.width
float height = barcode.height
PdfBoxGraphics2D pdfBoxGraphics2D = new PdfBoxGraphics2D(pdfDocument.pdDocument, width, height)
BarcodeGraphicsRenderer renderer = new BarcodeGraphicsRenderer(pdfBoxGraphics2D, null, 1.0d,
java.awt.Color.WHITE, java.awt.Color.BLACK, false, false)
renderer.render(symbol)
renderer.close()
PDFormXObject xFormObject = pdfBoxGraphics2D.getXFormObject()
Matrix matrix = new Matrix()
matrix.translate(x, y)
contentStream.saveGraphicsState()
contentStream.transform(matrix)
contentStream.drawForm(xFormObject)
contentStream.restoreGraphicsState()
}
private static Symbol create(SymbolType symbolType) {
for (SymbolProvider symbolProvider : ServiceLoader.load(SymbolProvider)) {
if (symbolProvider.canProvide(symbolType)) {
return symbolProvider.provide()
}
}
throw new IllegalArgumentException('unknown symbol type ' + symbolType)
}
private static PDFormXObject createXObject(PDDocument document, float x, float y) {
PDFormXObject xFormObject = new PDAppearanceStream(document)
xFormObject.setResources(new PDResources())
xFormObject.setBBox(new PDRectangle(x, y))
return xFormObject
}
}

View file

@ -0,0 +1,136 @@
package org.xbib.graphics.pdfbox.groovy.test
import org.apache.pdfbox.pdmodel.PDDocument
import org.apache.pdfbox.pdmodel.PDPage
import org.apache.pdfbox.pdmodel.PDPageContentStream
import org.apache.pdfbox.pdmodel.common.PDRectangle
import org.apache.pdfbox.pdmodel.font.PDType1Font
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject
import org.apache.pdfbox.util.Matrix
import org.junit.jupiter.api.Test
import org.xbib.graphics.barcode.Code3Of9
import org.xbib.graphics.barcode.HumanReadableLocation
import org.xbib.graphics.barcode.render.BarcodeGraphicsRenderer
import org.xbib.graphics.pdfbox.PdfBoxGraphics2D
import java.awt.Color
import java.awt.Graphics2D
import java.awt.Rectangle
import java.awt.image.BufferedImage
import java.nio.file.Files
import java.nio.file.Paths
class PdfBoxBarcodeTest {
@Test
void testBarcodeImage() {
PDDocument document = new PDDocument()
PDPage page = new PDPage(PDRectangle.A4)
document.addPage(page)
PDPageContentStream contentStream = new PDPageContentStream(document, page)
BarcodeCreator creator = new ImageBarcodeRenderer(document, contentStream)
createBarcode(page, creator)
createText(page, contentStream)
String filename = "build/pdfbox-with-barcode-image.pdf"
OutputStream outputStream = Files.newOutputStream(Paths.get(filename))
document.save(outputStream)
}
@Test
void testBarcodeEmbedded() {
PDDocument document = new PDDocument()
PDPage page = new PDPage(PDRectangle.A4)
document.addPage(page)
PDPageContentStream contentStream = new PDPageContentStream(document, page)
BarcodeCreator creator = new PdfboxBarcodeRenderer(document, contentStream)
createBarcode(page, creator)
createText(page, contentStream)
String filename = "build/pdfbox-with-barcode-embedded.pdf"
OutputStream outputStream = Files.newOutputStream(Paths.get(filename))
document.save(outputStream)
}
private void createBarcode(PDPage page, BarcodeCreator barcodeCreator) {
float x = 32.0f
float y = page.getBBox().height - 100.0f
float width = 150f
float height = 75f
Code3Of9 code3Of9 = new Code3Of9()
code3Of9.setContent('1234567890')
code3Of9.setBarHeight(height as int)
code3Of9.setHumanReadableLocation(HumanReadableLocation.BOTTOM)
barcodeCreator.create(x, y, width, height, code3Of9)
}
private static void createText(PDPage page, PDPageContentStream contentStream) {
contentStream.moveTo(32.0f, (page.getBBox().height - 80f) as float)
contentStream.beginText()
contentStream.setFont(PDType1Font.HELVETICA, 12f)
contentStream.showText("Hello World")
contentStream.endText()
contentStream.close()
}
interface BarcodeCreator {
void create(float x, float y, float width, float height, Code3Of9 code3Of9)
}
class ImageBarcodeRenderer implements BarcodeCreator {
PDDocument document
PDPageContentStream contentStream
ImageBarcodeRenderer(PDDocument document, PDPageContentStream contentStream) {
this.document = document
this.contentStream = contentStream
}
@Override
void create(float x, float y, float width, float height, Code3Of9 code3Of9) {
BufferedImage bufferedImage = new BufferedImage(width as int, height as int, BufferedImage.TYPE_BYTE_GRAY)
Graphics2D g2d = bufferedImage.createGraphics()
Rectangle rectangle = new Rectangle(0, 0, width as int, height as int)
BarcodeGraphicsRenderer renderer = new BarcodeGraphicsRenderer(g2d, rectangle, 1.0d,
Color.WHITE, Color.BLACK, false, false)
renderer.render(code3Of9)
renderer.close()
PDImageXObject img = LosslessFactory.createFromImage(document, bufferedImage)
Matrix matrix = new Matrix()
matrix.translate(x, y)
contentStream.saveGraphicsState()
contentStream.transform(matrix)
contentStream.drawImage(img, 0f, 0f, width, height)
contentStream.restoreGraphicsState()
}
}
class PdfboxBarcodeRenderer implements BarcodeCreator {
PDDocument document
PDPageContentStream contentStream
PdfboxBarcodeRenderer(PDDocument document, PDPageContentStream contentStream) {
this.document = document
this.contentStream = contentStream
}
@Override
void create(float x, float y, float width, float height, Code3Of9 code3Of9) {
PdfBoxGraphics2D pdfBoxGraphics2D = new PdfBoxGraphics2D(document, width, height)
Rectangle rectangle = new Rectangle(0, 0, width as int, height as int)
BarcodeGraphicsRenderer renderer = new BarcodeGraphicsRenderer(pdfBoxGraphics2D, rectangle, 1.0d,
Color.WHITE, Color.BLACK, false, false)
renderer.render(code3Of9)
renderer.close()
PDFormXObject xFormObject = pdfBoxGraphics2D.getXFormObject()
Matrix matrix = new Matrix()
matrix.translate(x, y)
contentStream.saveGraphicsState()
contentStream.transform(matrix)
contentStream.drawForm(xFormObject)
contentStream.restoreGraphicsState()
}
}
}

View file

@ -2,6 +2,7 @@ package org.xbib.graphics.pdfbox.groovy.test
import groovy.util.logging.Log4j2
import org.junit.Test
import org.xbib.graphics.barcode.SymbolType
import org.xbib.graphics.pdfbox.groovy.builder.PdfDocumentBuilder
import java.nio.file.Files
@ -114,6 +115,36 @@ class PdfDocumentBuilderTest {
}
}
@Test
void testPdfWithBarcode() {
OutputStream outputStream = Files.newOutputStream(Paths.get('build/barcode.pdf'))
outputStream.withCloseable {
PdfDocumentBuilder builder = new PdfDocumentBuilder(outputStream)
builder.create {
document(font: [family: 'Helvetica'], margin: [top: 1.cm]) {
paragraph(margin: [left: 7.mm, top: 0.cm]) {
text "Hello World 1"
}
paragraph(margin: [left: 7.mm, top: 2.cm]) {
barcode(width: 6.cm, height: 2.cm, value: '20180123456', type: SymbolType.CODE39)
}
paragraph(margin: [left: 7.mm, top: 0.cm]) {
text "Hello World 2"
}
paragraph(margin: [left: 7.mm, top: 1.cm, bottom: 1.cm]) {
barcode(width: 10.cm, height: 0.5.cm, value: 'ABCDEFGHIJKLMN', type: SymbolType.CODE39)
}
paragraph(margin: [left: 7.mm, top: 0.cm]) {
text "Hello World 3"
}
paragraph(margin: [left: 7.mm, top: 4.cm]) {
barcode(width: 6.cm, height: 4.cm, value: 'Hello', type: SymbolType.QRCODE)
}
}
}
}
}
@Test
void testPdfWithImage() {
byte[] logo = getClass().getResourceAsStream('/img/logo-print.png').bytes
@ -121,7 +152,9 @@ class PdfDocumentBuilderTest {
outputStream.withCloseable {
PdfDocumentBuilder builder = new PdfDocumentBuilder(outputStream)
List layout = [
[key: 'Typ', value: 'Online', 'bold': true]
[key: 'A', value: '1', 'bold': true],
[key: 'B', value: '2', 'bold': true],
[key: 'C', value: '3', 'bold': true]
]
builder.create {
document(font: [family: 'Helvetica'], margin: [top: 1.cm]) {
@ -169,23 +202,6 @@ class PdfDocumentBuilderTest {
}
}
@Test
void testPdfWithBarcode() {
OutputStream outputStream = Files.newOutputStream(Paths.get('build/barcode.pdf'))
outputStream.withCloseable {
PdfDocumentBuilder builder = new PdfDocumentBuilder(outputStream)
builder.create {
document {
paragraph {
text "Hello World"
barcode(x: 10.cm, y: 1.cm, width: 6.cm, height: 2.cm, value: '20180123456')
}
paragraph "Hello World bottom"
}
}
}
}
@Test
void testPdfWithCaron() {
List fontdefs = [

View file

@ -0,0 +1,8 @@
This work is based on
https://github.com/rototor/pdfbox-graphics2d
as of December 2020
APache 2.0 License

View file

@ -5,7 +5,6 @@ import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
import org.apache.pdfbox.pdmodel.graphics.color.PDICCBased;
import org.xbib.graphics.pdfbox.color.DefaultColorMapper;
import java.awt.Color;
import java.awt.color.ICC_ColorSpace;

View file

@ -0,0 +1,5 @@
module org.xbib.graphics.printer {
exports org.xbib.graphics.printer;
requires java.logging;
requires transitive java.desktop;
}

View file

@ -1,4 +1,4 @@
package org.xbib.graphics.ghostscript;
package org.xbib.graphics.printer;
import javax.print.Doc;
import javax.print.DocFlavor;

View file

@ -1,4 +1,4 @@
package org.xbib.graphics.ghostscript;
package org.xbib.graphics.printer;
import javax.print.PrintService;
import javax.print.attribute.standard.Media;

View file

@ -1,7 +1,7 @@
package org.xbib.graphics.ghostscript.test;
package org.xbib.graphics.printer.test;
import org.junit.jupiter.api.Test;
import org.xbib.graphics.ghostscript.PrintUtility;
import org.xbib.graphics.printer.PrintUtility;
import java.util.logging.Level;
import java.util.logging.Logger;

View file

@ -9,3 +9,4 @@ include 'graphics-ghostscript'
include 'graphics-pdfbox'
include 'graphics-pdfbox-layout'
include 'graphics-pdfbox-groovy'
include 'graphics-printer'