First commit

This commit is contained in:
2026-08-25 10:37:57 +08:00
commit b3b8a40f77
1601 changed files with 275999 additions and 0 deletions
+119
View File
@@ -0,0 +1,119 @@
/*
* barcode.h -- definitions for libbarcode
*
* Copyright (c) 1999 Alessandro Rubini (rubini@gnu.org)
* Copyright (c) 1999 Prosa Srl. (prosa@prosa.it)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _BARCODE_H_
#define _BARCODE_H_
#include <stdio.h>
#define BARCODE_VERSION "0.98"
#define BARCODE_VERSION_INT 9800
/*
* The object
*/
struct Barcode_Item {
int flags; /* type of encoding and decoding */
char *ascii; /* malloced */
char *partial; /* malloced too */
char *textinfo; /* information about text positioning */
char *encoding; /* code name, filled by encoding engine */
int width, height; /* output units */
int xoff, yoff; /* output units */
int margin; /* output units */
double scalef; /* requested scaling for barcode */
int error; /* an errno-like value, in case of failure */
};
/*
* The flags field
*/
#define BARCODE_DEFAULT_FLAGS 0x00000000
#define BARCODE_ENCODING_MASK 0x000000ff /* 256 possibilites... */
#define BARCODE_NO_ASCII 0x00000100 /* avoid text in output */
#define BARCODE_NO_CHECKSUM 0x00000200 /* avoid checksum in output */
#define BARCODE_OUTPUT_MASK 0x000ff000 /* 256 output types */
#define BARCODE_OUT_EPS 0x00001000
#define BARCODE_OUT_PS 0x00002000
#define BARCODE_OUT_PCL 0x00004000 /* by Andrea Scopece */
/* PCL_III 0x00008000 */
#define BARCODE_OUT_PCL_III 0x0000C000
#define BARCODE_OUT_NOHEADERS 0x00100000 /* no header nor footer */
enum {
BARCODE_ANY = 0, /* choose best-fit */
BARCODE_EAN,
BARCODE_UPC, /* upc == 12-digit ean */
BARCODE_ISBN, /* isbn numbers (still EAN13) */
BARCODE_39, /* code 39 */
BARCODE_128, /* code 128 (a,b,c: autoselection) */
BARCODE_128C, /* code 128 (compact form for digits) */
BARCODE_128B, /* code 128, full printable ascii */
BARCODE_I25, /* interleaved 2 of 5 (only digits) */
BARCODE_128RAW, /* Raw code 128 (by Leonid A. Broukhis) */
BARCODE_CBR, /* Codabar (by Leonid A. Broukhis) */
BARCODE_MSI, /* MSI (by Leonid A. Broukhis) */
BARCODE_PLS, /* Plessey (by Leonid A. Broukhis) */
BARCODE_93 /* code 93 (by Nathan D. Holmes) */
};
#define BARCODE_DEFAULT_MARGIN 10
#ifdef __cplusplus
extern "C" {
#endif
/*
* Create and destroy barcode structures
*/
extern struct Barcode_Item *Barcode_Create(char *text);
extern int Barcode_Delete(struct Barcode_Item *bc);
/*
* Encode and print
*/
extern int Barcode_Encode(struct Barcode_Item *bc, int flags);
extern int Barcode_Print(struct Barcode_Item *bc, FILE *f, int flags);
/*
* Choose the position
*/
extern int Barcode_Position(struct Barcode_Item *bc, int wid, int hei,
int xoff, int yoff, double scalef);
/*
* Do it all in one step
*/
extern int Barcode_Encode_and_Print(char *text, FILE *f, int wid, int hei,
int xoff, int yoff, int flags);
/*
* Return current version (integer and string)
*/
extern int Barcode_Version(char *versionname);
#ifdef __cplusplus
}
#endif
#endif /* _BARCODE_H_ */
+177
View File
@@ -0,0 +1,177 @@
/*
* cmdline.c -- parse a command line using getopt, environment and defaults
*
* Copyright (c) 1999 Alessandro Rubini (rubini@gnu.org)
* Copyright (c) 1999 Prosa Srl. (prosa@prosa.it)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* Changes:
* Michele Comitini (mcm@glisco.it): better handling of numeric type args.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef NO_GETOPT
/* use replacement */
#include "compat/getopt.h"
#else
#include <getopt.h>
#endif
#include "cmdline.h"
/* In case of error, print help string and return error (-1) */
int commandline_errormsg(FILE *f, struct commandline *args,
char *prgname, char *messagehead)
{
char *buffer;
char *buffer2;
int len;
struct commandline *ptr;
if (!messagehead) {
fprintf(f,"%s: Error in cmdline\nPossible options:\n",prgname);
} else {
fprintf(f,"%s: %s",prgname,messagehead);
}
for (ptr = args; ptr->option; ptr++) {
if (ptr->descrip) {
len = strlen(ptr->descrip);
len += ptr->default_v ? strlen(ptr->default_v) : 6;
len += ptr->env ? strlen(ptr->env) : 6;
buffer2 = malloc(len+3); /* 3 to be safe :) */
len += 32;
if (buffer2) {
buffer = malloc(len);
if (buffer) {
sprintf(buffer2, ptr->descrip,
ptr->default_v ? ptr->default_v : "(none)",
ptr->env ? ptr->env : "(none)");
sprintf(buffer, " -%c %s %s", ptr->option,
ptr->type ? "<arg>" : " ", buffer2);
fprintf(f, "%s\n",buffer);
free(buffer);
}
free(buffer2);
}
}
}
return -1;
}
/*
* Associate formats to type.
*/
struct type_fmt {
enum option_type type;
char *fmt;
};
static struct type_fmt formats[] = {
{CMDLINE_I, "%i%s"}, /* the trailing "%s" is used for error check */
{CMDLINE_D, "%d%s"},
{CMDLINE_X, "%x%s"},
{CMDLINE_O, "%o%s"},
{CMDLINE_F, "%lf%s"},
{CMDLINE_P, "%p%s"},
{0, NULL} /* If we get here, it's CMDLINE_S: no sscanf buf strcpy() */
};
/* Parse one argument (default or provided) */
static int commandline_oneopt(struct commandline *ptr, char *value)
{
struct type_fmt *tptr;
char *trash = value ? strdup(value) : NULL;
/* convert it, if needed */
if ((ptr->type != CMDLINE_NONE) && ptr->result) {
for (tptr = formats; tptr->type; tptr++)
if (tptr->type == ptr->type)
break;
if (!tptr->type) /* not found: it is a string */
*(char **)(ptr->result) = value;
else
if (sscanf(value, tptr->fmt, ptr->result, trash)!=1) {
free(trash);
return -1;
}
}
if (trash)
free(trash);
if ((ptr->type == CMDLINE_NONE) && ptr->result) /* no type, just count */
(*(int *)(ptr->result))++;
/* call the function, if needed */
if (ptr->fun) {
if (ptr->type) {
if (ptr->result) return ptr->fun(ptr->result); /* converted */
return ptr->fun(value); /* type, but not converted */
}
return ptr->fun(NULL); /* no type: just call it */
}
return 0;
}
/* The main function */
int commandline(struct commandline *args, int argc, char **argv,
char *errorhead)
{
struct commandline *ptr;
char *getopt_desc = (char *)calloc(512, 1);
int desc_offset = 0;
int opt, retval;
char *value;
/* Build getopt string and process defaults values */
for (ptr = args; ptr->option; ptr++) {
getopt_desc[desc_offset++] = ptr->option;
if (ptr->type) getopt_desc[desc_offset++] = ':';
value = NULL;
if (ptr->env)
value = getenv(ptr->env);
if (!value)
value = ptr->default_v;
if (value && (retval = commandline_oneopt(ptr, value))) {
/*
* if the function returns a specific (not -1) value, it already
* printed its message, so avoid the generic help
*/
if (retval == -1)
commandline_errormsg(stderr, args, argv[0], errorhead);
return retval;
}
}
/* Run getopt and process material */
while ((opt = getopt(argc, argv, getopt_desc)) != -1) {
for (ptr = args; ptr->option; ptr++)
if (opt == ptr->option)
break;
if (!ptr->option) /* unknown option */
return commandline_errormsg(stderr, args, argv[0], errorhead);
if ( (retval = commandline_oneopt(ptr, optarg)) ) { /* wrong arg */
if (retval == -1)
commandline_errormsg(stderr, args, argv[0], errorhead);
return retval;
}
}
return 0;
}
+58
View File
@@ -0,0 +1,58 @@
/*
* cmdline.h -- generic commandline editing (uses getopt, only short)
*
* Copyright (c) 1999 Alessandro Rubini (rubini@gnu.org)
* Copyright (c) 1999 Prosa Srl. (prosa@prosa.it)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
*/
/*
* The options may have different arguments of different type
*/
enum option_type {
CMDLINE_NONE=0, /* no argument after option */
CMDLINE_I, /* integer (any base) */
CMDLINE_D, /* decimal integer */
CMDLINE_X, /* hex integer */
CMDLINE_O, /* octal integer */
CMDLINE_S, /* string */
CMDLINE_F, /* double float */
CMDLINE_P, /* pointer */
};
struct commandline {
int option; /* Single byte: option id */
int type; /* Type of argument, used in sscanf */
void *result; /* Store data here, if non null */
int (*fun)(void *); /* Call if defined: arg is "result" or input string */
char *env; /* Where to get runtime defaults, may be NULL */
char *default_v; /* The compile-time default, may be NULL */
char *descrip; /* For err msg. May have %s's for default and env */
};
/* returns: 0 or -1. "optarg" is global (see getopt) */
extern int commandline(struct commandline *args,
int argc, char **argv, char *errorhead);
/* prints an error message based on "args" */
extern int commandline_errormsg(FILE *f, struct commandline *args,
char *prgname, char *messagehead);
+182
View File
@@ -0,0 +1,182 @@
/*
* codabar.c -- encoding for Codabar
*
* Copyright (c) 2000 Leonid A. Broukhis (leob@mailcom.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "barcode.h"
/* this is ordered in decades to simplify encoding */
static char alphabet[] =
"0123456789" "-$:/.+ABCD";
#define CODE_A 16
#define CODE_B 17
#define NARROW 12
#define WIDE 14
/* Patterns */
static char *patterns[] = {
"1111133","1111331","1113113","3311111","1131131",
"3111131","1311113","1311311","1331111","3113111",
"1113311","1133111","3111313","3131113","3131311",
"1131313","1133131","1313113","1113133","1113331" };
/*
* Check that the text can be encoded. Returns 0 or -1.
* If it's all lowecase convert to uppercase and accept it.
* If the first character is a letter (A to D), the last one must be too;
* no other character should be a letter.
*/
int Barcode_cbr_verify(unsigned char *text)
{
int i, lower=0, upper=0;
int startpresent = 0;
if (!strlen(text))
return -1;
for (i=0; text[i]; i++) {
char * pos;
if (isupper(text[i])) upper++;
if (islower(text[i])) lower++;
pos = strchr(alphabet,toupper(text[i]));
if (!pos)
return -1;
if (i == 0 && pos - alphabet >= CODE_A)
startpresent = 1;
else if (pos - alphabet >= CODE_A &&
(!startpresent || i != strlen(text) - 1))
return -1;
}
if (lower && upper)
return -1;
return 0;
}
static int add_one(char *ptr, int code)
{
sprintf(ptr,"1%s", /* separator */ patterns[code]);
return 0;
}
/*
* The encoding functions fills the "partial" and "textinfo" fields.
* Lowercase chars are converted to uppercase
*/
int Barcode_cbr_encode(struct Barcode_Item *bc)
{
static char *text;
static char *partial; /* dynamic */
static char *textinfo; /* dynamic */
char *c, *ptr, *textptr;
int i, code, textpos, usesum, checksum = 0, startpresent;
if (bc->partial)
free(bc->partial);
if (bc->textinfo)
free(bc->textinfo);
bc->partial = bc->textinfo = NULL; /* safe */
if (!bc->encoding)
bc->encoding = strdup("codabar");
text = bc->ascii;
if (!text) {
bc->error = EINVAL;
return -1;
}
/* the partial code is 8 * (head + text + check + tail) + margin + term. */
partial = malloc( (strlen(text) + 3) * 8 + 2);
if (!partial) {
bc->error = errno;
return -1;
}
/* the text information is at most "nnn:fff:c " * (strlen + check) +term */
textinfo = malloc(10*(strlen(text) + 1) + 2);
if (!textinfo) {
bc->error = errno;
free(partial);
return -1;
}
ptr = partial;
textptr = textinfo;
textpos = 0;
usesum = bc->flags & BARCODE_NO_CHECKSUM ? 0 : 1;
/* if no start character specified, A is used as a start character */
if (!isalpha(text[0])) {
add_one(ptr, CODE_A);
ptr += strlen(ptr);
textpos = WIDE;
checksum = CODE_A;
startpresent = 0;
} else {
startpresent = 1;
}
for (i=0; i<strlen(text); i++) {
c = strchr(alphabet, toupper(text[i]));
if (!c) {
bc->error = EINVAL; /* impossible if text is verified */
free(partial);
free(textinfo);
return -1;
}
code = c - alphabet;
add_one(ptr, code);
sprintf(textptr, "%i:12:%c ", textpos, toupper(text[i]));
textpos += code < 12 ? NARROW : WIDE;
textptr += strlen(textptr);
ptr += strlen(ptr);
checksum += code;
if (startpresent && usesum && i == strlen(text) - 2) {
/* stuff a check symbol before the stop */
c = strchr(alphabet, toupper(text[i+1]));
if (!c) /* impossible */
continue;
code = c - alphabet;
checksum += code;
/* Complement to a multiple of 16 */
checksum = (checksum + 15) / 16 * 16 - checksum;
add_one(ptr, checksum);
ptr += strlen(ptr);
}
}
if (!startpresent) {
if (usesum) {
/* if no start character specified, B is used as a stop char */
checksum += CODE_B;
checksum = (checksum + 15) / 16 * 16 - checksum;
add_one(ptr, checksum);
ptr += strlen(ptr);
}
add_one(ptr, CODE_B);
}
bc->partial = partial;
bc->textinfo = textinfo;
return 0;
}
+618
View File
@@ -0,0 +1,618 @@
/*
* code128.c -- encoding for code128 (A, B, C)
*
* Copyright (c) 1999,2000 Alessandro Rubini (rubini@gnu.org)
* Copyright (c) 1999 Prosa Srl. (prosa@prosa.it)
* Copyright (c) 2000 Leonid A. Broukhis (leob@mailcom.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "barcode.h"
//0 b1a2a4 123221 223211 221132 221231 213212 223112 312131 311222 314111 b3c1a1b
static char *codeset[] = {
"212222", "222122", "222221", "121223", "121322", /* 0 - 4 */
"131222", "122213", "122312", "132212", "221213",
"221312", "231212", "112232", "122132", "122231", /* 10 - 14 */
"113222", "123122", "123221", "223211", "221132",
"221231", "213212", "223112", "312131", "311222", /* 20 - 24 */
"321122", "321221", "312212", "322112", "322211",
"212123", "212321", "232121", "111323", "131123", /* 30 - 34 */
"131321", "112313", "132113", "132311", "211313",
"231113", "231311", "112133", "112331", "132131", /* 40 - 44 */
"113123", "113321", "133121", "313121", "211331",
"231131", "213113", "213311", "213131", "311123", /* 50 - 54 */
"311321", "331121", "312113", "312311", "332111",
"314111", "221411", "431111", "111224", "111422", /* 60 - 64 */
"121124", "121421", "141122", "141221", "112214",
"112412", "122114", "122411", "142112", "142211", /* 70 - 74 */
"241211", "221114", "413111", "241112", "134111",
"111242", "121142", "121241", "114212", "124112", /* 80 - 84 */
"124211", "411212", "421112", "421211", "212141",
"214121", "412121", "111143", "111341", "131141", /* 90 - 94 */
"114113", "114311", "411113", "411311", "113141",
"114131", "311141", "411131", "b1a4a2", "b1a2a4", /* 100 - 104 */
"b1a2c2", "b3c1a1b"
};
// "114131", "311141", "411131", "211412", "211214", /* 100 - 104 */
// "211232", "2331112"
//0 b1a2a4 123221 223211 221132 221231 213212 223112 312131 311222 314111 b3c1a1b
// 211214 2331112
/*
1,1,4,1,3,1,// CodeB FNC4 CodeB
3,1,1,1,4,1,// FNC4 CodeA CodeA
4,1,1,1,3,1,// FNC1 FNC1 FNC1
2,1,1,4,1,2,// StartA
2,1,1,2,1,4,// StartB
2,1,1,2,3,2,// StartC
2,3,3,1,1,1,2,// Stop
*/
#define START_A 103
#define START_B 104
#define START_C 105
#define STOP 106
#define SHIFT 98 /* only A and B */
#define CODE_A 101 /* only B and C */
#define CODE_B 100 /* only A and C */
#define CODE_C 99 /* only A and B */
#define FUNC_1 102 /* all of them */
#define FUNC_2 97 /* only A and B */
#define FUNC_3 96 /* only A and B */
/* FUNC_4 is CODE_A when in A and CODE_B when in B */
#define SYMBOL_WID 11 /* all of them are 11-bar wide */
/*
* code 128-b includes all printable ascii chars
*/
int Barcode_128b_verify(unsigned char *text)
{
if (text[0] == '\0')
return -1;
while (*text && *text>=32 && !(*text&0x80))
text++;
if (*text)
return -1; /* a non-ascii char */
return 0; /* ok */
}
int Barcode_128b_encode(struct Barcode_Item *bc)
{
static char *text;
static char *partial; /* dynamic */
static char *textinfo; /* dynamic */
char *textptr;
int i, code, textpos, checksum = 0;
if (bc->partial)
free(bc->partial);
if (bc->textinfo)
free(bc->textinfo);
bc->partial = bc->textinfo = NULL; /* safe */
if (!bc->encoding)
bc->encoding = strdup("code 128-B");
text = bc->ascii;
if (!text) {
bc->error = EINVAL;
return -1;
}
/* the partial code is 6* (head + text + check + tail) + final + term. */
partial = malloc( (strlen(text) + 4) * 6 +2);
if (!partial) {
bc->error = errno;
return -1;
}
/* the text information is at most "nnn:fff:c " * strlen +term */
textinfo = malloc(10*strlen(text) + 2);
if (!textinfo) {
bc->error = errno;
free(partial);
return -1;
}
/* up to now, it was the same code as other encodings */
strcpy(partial, "0"); /* the first space */
strcat(partial, codeset[START_B]);
checksum += START_B; /* the start char is counted in the checksum */
textptr = textinfo;
textpos = SYMBOL_WID;
for (i=0; i<strlen(text); i++) {
if ( text[i] < 32 || (text[i] & 0x80)) {
bc->error = EINVAL; /* impossible if text is verified */
free(partial);
free(textinfo);
return -1;
}
code = text[i]-32;
strcat(partial, codeset[code]);
checksum += code * (i+1); /* first * 1 + second * 2 + third * 3... */
sprintf(textptr, "%i:12:%c ", textpos, text[i]);
textptr += strlen(textptr);
textpos += SYMBOL_WID; /* width of each code */
}
/* Add the checksum, independent of BARCODE_NO_CHECKSUM */
checksum %= 103;
strcat(partial, codeset[checksum]);
/* and the end marker */
strcat(partial, codeset[STOP]);
bc->partial = partial;
bc->textinfo = textinfo;
return 0;
}
/*
* code 128-c is only digits, but two per symbol
*/
int Barcode_128c_verify(unsigned char *text)
{
if (text[0] == '\0')
return -1;
/* must be an even number of digits */
if (strlen(text)%2)
return -1;
/* and must be all digits */
for (; *text; text++)
if (!isdigit(*text))
return -1;
return 0;
}
int Barcode_128c_encode(struct Barcode_Item *bc)
{
static char *text;
static char *partial; /* dynamic */
static char *textinfo; /* dynamic */
char *textptr;
int i, code, textpos, checksum = 0;
if (bc->partial)
free(bc->partial);
if (bc->textinfo)
free(bc->textinfo);
bc->partial = bc->textinfo = NULL; /* safe */
if (!bc->encoding)
bc->encoding = strdup("code 128-C");
text = bc->ascii;
if (!text) {
bc->error = EINVAL;
return -1;
}
/* the partial code is 6* (head + text + check + tail) + final + term. */
partial = malloc( (strlen(text) + 3) * 6 +2);
if (!partial) {
bc->error = errno;
return -1;
}
/* the text information is at most "nnn.5:fff:c " * strlen +term */
textinfo = malloc(12*strlen(text) + 2);
if (!textinfo) {
bc->error = errno;
free(partial);
return -1;
}
strcpy(partial, "0"); /* the first space */
strcat(partial, codeset[START_C]);
checksum += START_C; /* the start char is counted in the checksum */
textptr = textinfo;
textpos = SYMBOL_WID;
for (i=0; text[i]; i+=2) {
if (!isdigit(text[i]) || !isdigit(text[i+1])) {
bc->error = EINVAL; /* impossible if text is verified */
free(partial);
free(textinfo);
return -1;
}
code = (text[i]-'0') * 10 + text[i+1]-'0';
strcat(partial, codeset[code]);
checksum += code * (i/2+1); /* first * 1 + second * 2 + third * 3... */
/* print as "%s", because we have ".5" positions */
sprintf(textptr, "%g:9:%c %g:9:%c ", (double)textpos, text[i],
textpos + (double)SYMBOL_WID/2, text[i+1]);
textptr += strlen(textptr);
textpos += SYMBOL_WID; /* width of each code */
}
/* Add the checksum, independent of BARCODE_NO_CHECKSUM */
checksum %= 103;
strcat(partial, codeset[checksum]);
/* and the end marker */
strcat(partial, codeset[STOP]);
bc->partial = partial;
bc->textinfo = textinfo;
return 0;
}
/*
* generic (full-featured) code128 implementation: it selects between
* A, B, C according to the data being encoded. F1, F2, F3, F4 are expressed
* using ascii chars 0xc1, 0xc2, 0xc3, 0xc4 (0301, 0302, 0303, 0304).
* Char '\0' is expressed by 0x80 (0200).
*/
int Barcode_128_verify(unsigned char *text)
{
if (text[0] == '\0')
return -1;
while (*text && (*text<=0x80 || (*text >= 0xc1 && *text <= 0xc4)))
text++;
if (*text)
return -1; /* unencodable character */
return 0; /* ok */
}
/*
* These functions are extracted from Barcode_128_encode for clarity.
* It deals with choosing the symbols used to represent the text
* and returns a dynamic array of integers, terminated by -1.
*
* The algorithm used in choosing the codes comes from App 2 of
* "El Codigo Estandar EAN/UCC 128", courtesy of AECOC, Spain.
* Thanks to Dani Pardo for getting permission and giving me a copy
* of the document
*/
#define NEED_CODE_A(c) ((c)<32 || (c)==0x80)
#define NEED_CODE_B(c) ((c)>=96 && (c)<128)
static int Barcode_a_or_b(unsigned char *text)
{
for ( ; *text; text++) {
if (NEED_CODE_A(*text))
return 'A';
if (NEED_CODE_B(*text))
return 'B';
}
return 0; /* any */
}
/* code is either 'A' or 'B', and value must be valid */
static int Barcode_encode_as(int code, int value)
{
/* first check the special chars */
if (value == 0xC1) return FUNC_1;
if (value == 0xC2) return FUNC_2;
if (value == 0xC3) return FUNC_3;
if (value == 0xC4) { /* F4 */
if (code == 'A') return CODE_A;
return CODE_B;
}
/* then check ascii values */
if (value >= 0x20 && value <= 0x5F)
return value - 0x20; /* both codes */
if (value == 0x80) return 64; /* code A */
if (value < 0x20) return value+64; /* code A */
if (value >= 0x60) return value - 0x20; /* code B */
/* can't happen */
return -1;
}
static int *Barcode_128_make_array(struct Barcode_Item *bc, int *lptr)
{
int len, *codes;
unsigned char *s;
int i=0, j, code, checksum;
/* allocate twice the text length + 5, as this is the worst case */
len = 2 * strlen(bc->ascii) + 5;
codes = malloc(len * sizeof(int));
s = bc->ascii;
/* choose the starting code */
if (s[2]=='\0' && isdigit(s[0]) && isdigit(s[1])) {
code = 'C';
} else if (isdigit(s[0])&&isdigit(s[1]) && isdigit(s[2])&&isdigit(s[3])) {
code = 'C';
} else {
code = Barcode_a_or_b(s);
if (!code) code = 'B'; /* default */
}
codes[i++] = START_A + code - 'A';
for (s = bc->ascii; *s; /* increments are in the loop */) {
switch(code) {
case 'C':
if (s[0] == 0xC1) { /* F1 is valid */
codes[i++] = FUNC_1;
s++;
} else if (isdigit(s[0]) && isdigit(s[1])) {
/* encode two digits */
codes[i++] = (s[0]-'0') * 10 + s[1]-'0';
s += 2;
} else {
/* change code */
code = Barcode_a_or_b(s);
if (!code) code = 'B';
codes[i++] = (code == 'A') ? CODE_A : CODE_B;
}
break;
case 'B':
case 'A':
for (j=0; isdigit(s[j]); j++)
;
if (j>=4) { /* if there are 4 or more digits, turn to C */
if (j&1) {
/* odd number: encode one first */
codes[i++] = *(s++) - ' ';
}
codes[i++] = CODE_C;
code = 'C';
} else if (code == 'A' && NEED_CODE_B(*s)) {
/* check whether we should use SHIFT or change code */
j = Barcode_a_or_b(s+1);
if (j == 'B') {
codes[i++] = CODE_B;
code = 'B';
} else {
codes[i++] = SHIFT;
codes[i++] = Barcode_encode_as('B', *s);
s++;
}
} else if (code == 'B' && NEED_CODE_A(*s)) {
/* check whether we should use SHIFT or change code */
j = Barcode_a_or_b(s+1);
if (j == 'A') {
codes[i++] = CODE_A;
code = 'A';
} else {
codes[i++] = SHIFT;
codes[i++] = Barcode_encode_as('A', *s);
s++;
}
} else {
codes[i++] = Barcode_encode_as(code, *s);
s++;
}
break;
}
}
/* add the checksum */
checksum = codes[0];
for (j=1; j<i; j++)
checksum += j * codes[j];
checksum %= 103;
codes[i++] = checksum;
codes[i++] = STOP;
if (i > len) {
fprintf(stderr, "impossible: length is > allocated len\n");
}
*lptr = i;
return codes;
}
/*
* Encoding is tricky, in that we cannot print the ascii
* representation in an easy way. Therefore, just skip non-printable
* chars and try to fit the rest somehow.
*/
int Barcode_128_encode(struct Barcode_Item *bc)
{
static char *text;
static char *partial; /* dynamic */
static char *textinfo; /* dynamic */
char *textptr;
int *codes; /* dynamic */
int i, c, len;
double textpos, size, step;
if (bc->partial)
free(bc->partial);
if (bc->textinfo)
free(bc->textinfo);
bc->partial = bc->textinfo = NULL; /* safe */
if (!bc->encoding)
bc->encoding = strdup("code 128");
text = bc->ascii;
if (!text) {
bc->error = EINVAL;
return -1;
}
codes = Barcode_128_make_array(bc, &len);
if (!codes) return -1;
/* the partial code is 6*codelen + ini + term (+margin) */
partial = malloc( 6 * len + 4);
if (!partial) {
bc->error = errno;
free(codes);
return -1;
}
/* the text information is at most "nnn.n:ff.f:c " * strlen +term */
textptr = textinfo = malloc(13*strlen(text) + 2);
if (!textinfo) {
bc->error = errno;
free(partial);
free(codes);
return -1;
}
/* up to now, it was almost the same code as other encodings */
strcpy(partial, "0"); /* the first space */
for (i=0; i<len; i++) /* the symbols */
strcat(partial, codeset[codes[i]]);
/* avoid bars that fall lower than other bars */
for (i=0; partial[i]; i++)
if (isalpha(partial[i]))
partial[i] += '1' - 'a';
/*
* the accompanying text: reserve a space for every char.
* F[1-4] are rendered as spaces (separators), other unprintable chars
* are rendered as underscoress (placeholders)
*/
/*
* A size of 9 is good for code-C (used above), so 18 for each symbol,
* but we place an upper limit of 12 to avoid overlapping on the bars.
*/
size = (int)(180.0 * (len-3) / strlen(text) + .5) / 10.0;
if (size > 12.0) size = 12.0;
/* align the text to the left, using its natural size */
step = (int)(10 * (size/18.0 * SYMBOL_WID) + .5) / 10.0;
textpos = SYMBOL_WID;
for (i=0; i<strlen(text); i++) {
c = text[i];
if (c < 32 || c == 0x80) c = '_'; /* not printable */
if (c > 0xc0) c = ' '; /* F code */
sprintf(textptr, "%g:%g:%c ", textpos, size, c);
textptr += strlen(textptr);
textpos += step;
}
bc->partial = partial;
bc->textinfo = textinfo;
free(codes);
return 0;
}
/*
* A raw 128 code is given as a sequence of space separated numbers
* from 0 to 105, starting from the start code to be (Leonid)
*/
int Barcode_128raw_verify(unsigned char *text)
{
int n;
unsigned val;
if (!strlen(text))
return -1;
while (*text) {
if (sscanf(text, "%u%n", &val, &n) < 1)
return -1;
if (val > 105)
return -1;
text += n;
}
return 0;
}
int Barcode_128raw_encode(struct Barcode_Item *bc)
{
static char *text;
static char *partial; /* dynamic */
static char *textinfo; /* dynamic */
char *textptr;
int i, n, count, code, textpos, checksum = 0;
if (bc->partial)
free(bc->partial);
if (bc->textinfo)
free(bc->textinfo);
bc->partial = bc->textinfo = NULL; /* safe */
if (!bc->encoding)
bc->encoding = strdup("128raw");
text = bc->ascii;
if (!text) {
bc->error = EINVAL;
return -1;
}
/*
* length of partial code is unknown in advance, but it is
* at most 6* (1+text/2 + check + tail) + final + terminator
*/
partial = malloc( (3+ strlen(text)/2) * 6 + 2);
if (!partial) {
bc->error = errno;
return -1;
}
/* the text information is at most "nnn.5:fff:c " * 1+strlen/2 +term */
textinfo = malloc(12 * (1+strlen(text)/2) + 2);
if (!textinfo) {
bc->error = errno;
free(partial);
return -1;
}
strcpy(partial, "0"); /* the first space */
textptr = textinfo;
textpos = 0;
for (i=0, count = 0; i < strlen(text); count++) {
if (sscanf(text + i, "%u%n", &code, &n) < 1) {
bc->error = EINVAL; /* impossible if text is verified */
free(partial);
free(textinfo);
return -1;
}
strcat(partial, codeset[code]);
/*
* since the start code is part of the "raw" input, it is
* counted in the checksum by itself
*/
if (!count) checksum += code; /* the start code */
else checksum += code * count; /* first * 1 + second * 2 ... */
/*
* print as "%s", because we have ".5" positions
* also, use a size of 9 like codeC above, as each symbol is
* represented by two chars
*/
sprintf(textptr, "%g:9:%c %g:9:%c ", (double)textpos,
code >= 100 ? 'A' : code/10 + '0',
textpos + (double)SYMBOL_WID/2, code%10 + '0');
textptr += strlen(textptr);
textpos += SYMBOL_WID; /* width of each code */
i += n;
}
/* Add the checksum, independent of BARCODE_NO_CHECKSUM */
checksum %= 103;
strcat(partial, codeset[checksum]);
/* and the end marker */
strcat(partial, codeset[STOP]);
bc->partial = partial;
bc->textinfo = textinfo;
return 0;
}
+173
View File
@@ -0,0 +1,173 @@
/*
* code39.c -- encoding for code39
*
* Copyright (c) 1999 Alessandro Rubini (rubini@gnu.org)
* Copyright (c) 1999 Prosa Srl. (prosa@prosa.it)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "barcode.h"
/* this is ordered in decades to simplify encoding */
static char alphabet[] =
"1234567890" "ABCDEFGHIJ" "KLMNOPQRST" "UVWXYZ-. *" "$/+%";
/* the checksum alphabet has a different order */
static char checkbet[] =
"0123456789" "ABCDEFGHIJ" "KLMNOPQRST" "UVWXYZ-. $" "/+%";
/* The first 40 symbols repeat this bar pattern */
static char *bars[] = {
"31113","13113","33111","11313","31311",
"13311","11133","31131","13131","11331"};
/* The first 4 decades use these space patterns */
static char *spaces[] = {"1311","1131","1113","3111"};
/* the last four symbols are special */
static char *specialbars[] = {
"11111","11111","11111","11111"};
static char *specialspaces[] = {
"3331","3313","3133","1333"};
static char *fillers[]= {
"0a3a1c1c1a",
"1a3a1c1c1a"
};
/*
* Check that the text can be encoded. Returns 0 or -1.
* If it's all lowecase convert to uppercase and accept it
*/
int Barcode_39_verify(unsigned char *text)
{
int i, lower=0, upper=0;
if (text[0] == '\0')
return -1;
for (i=0; text[i]; i++) {
if (isupper(text[i])) upper++;
if (islower(text[i])) lower++;
if (!strchr(alphabet,toupper(text[i])))
return -1;
}
if (lower && upper)
return -1;
return 0;
}
static int add_one(char *ptr, int code)
{
char *b, *s;
if (code < 40) {
b = bars[code%10];
s = spaces[code/10];
} else {
b = specialbars[code-40];
s = specialspaces[code-40];
}
sprintf(ptr,"1%c%c%c%c%c%c%c%c%c", /* separator */
b[0], s[0], b[1], s[1], b[2], s[2],
b[3], s[3], b[4]);
return 0;
}
/*
* The encoding functions fills the "partial" and "textinfo" fields.
* Lowercase chars are converted to uppercase
*/
int Barcode_39_encode(struct Barcode_Item *bc)
{
static char *text;
static char *partial; /* dynamic */
static char *textinfo; /* dynamic */
char *c, *ptr, *textptr;
int i, code, textpos, checksum = 0;
if (bc->partial)
free(bc->partial);
if (bc->textinfo)
free(bc->textinfo);
bc->partial = bc->textinfo = NULL; /* safe */
if (!bc->encoding)
bc->encoding = strdup("code 39");
text = bc->ascii;
if (!text) {
bc->error = EINVAL;
return -1;
}
/* the partial code is 10* (head + text + check + tail) + margin + term. */
partial = malloc( (strlen(text) + 3) * 10 +2);
if (!partial) {
bc->error = errno;
return -1;
}
/* the text information is at most "nnn:fff:c " * strlen +term */
textinfo = malloc(10*strlen(text) + 2);
if (!textinfo) {
bc->error = errno;
free(partial);
return -1;
}
strcpy(partial, fillers[0]);
ptr = partial + strlen(partial);
textptr = textinfo;
textpos = 22;
for (i=0; text[i]; i++) {
c = strchr(alphabet, toupper(text[i]));
if (!c) {
bc->error = EINVAL; /* impossible if text is verified */
free(partial);
free(textinfo);
return -1;
}
code = c - alphabet;
add_one(ptr, code);
c = strchr(checkbet,*c);
if (c) /* the '*' is not there */
checksum += (c-checkbet);
sprintf(textptr, "%i:12:%c ", textpos, toupper(text[i]));
textpos += 16; /* width of each code */
textptr += strlen(textptr);
ptr += strlen(ptr);
}
/* Add the checksum */
if ( (bc->flags & BARCODE_NO_CHECKSUM)==0 ) {
code = (strchr(alphabet, checkbet[checksum % 43]) - alphabet);
add_one(ptr, code);
}
strcat(ptr, fillers[1]); /* end */
bc->partial = partial;
bc->textinfo = textinfo;
return 0;
}
+213
View File
@@ -0,0 +1,213 @@
/*
* code39.c -- encoding for code39
*
* Copyright (c) 1999 Alessandro Rubini (rubini@gnu.org)
* Copyright (c) 1999 Prosa Srl. (prosa@prosa.it)
* Copyright (c) 2001 Nathan D. Holmes / FedEx Services (ndholmes@fedex.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "barcode.h"
/* this is ordered in decades to simplify encoding */
static char alphabet[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%";
static char *codeset[] = {
"131112", "111213", "111312", "111411", "121113", /* 0 - 4 */
"121212", "121311", "111114", "131211", "141111", /* 5 - 9 */
"211113", "211212", "211311", "221112", "221211", /* A - E */
"231111", "112113", "112212", "112311", "122112", /* F - J */
"132111", "111123", "111222", "111321", "121122", /* K - O */
"131121", "212112", "212211", "211122", "211221", /* P - T */
"221121", "222111", "112122", "112221", "122121", /* U - Y */
"123111", "121131", "311112", "311211", "321111", /* Z - $ */
"112131", "113121", "211131", "121221", "312111", /* / - (%) */
"311121", "122211", "111141" /* (/) - (terminator) */
};
/* 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111111111111111111111111 */
/* 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122222222 */
/* 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 */
static char shiftset[] =
"%$$$$$$$$$$$$$$$$$$$$$$$$$$%%%%% /// ///// / /%%%%%% %%%%%%++++++++++++++++++++++++++%%%%%";
static char shiftset2[] =
"UABCDEFGHIJKLMNOPQRSTUVWXYZABCDE ABC FGHIJ L ZFGHIJV KLMNOWABCDEFGHIJLKMNOPQRSTUVWXYZPQRST";
#define START_STOP 47
#define EXTEND_DOLLAR 43
#define EXTEND_PERCENT 44
#define EXTEND_SLASH 45
#define EXTEND_PLUS 46
/*
* Check that the text can be encoded. Returns 0 or -1.
* All of ASCII-7 is accepted.
*/
int Barcode_93_verify(unsigned char *text)
{
int i;
if (!strlen(text))
return -1;
for (i=0; text[i]; i++) {
/* Test if beyond the range of 7-bit ASCII */
if ((int)text[i] > 127)
return -1;
}
return 0;
}
/*
* The encoding functions fills the "partial" and "textinfo" fields.
* Lowercase chars are converted to uppercase
*/
int Barcode_93_encode(struct Barcode_Item *bc)
{
static unsigned char *text;
static char *partial; /* dynamic */
static char *textinfo; /* dynamic */
char *c, *textptr;
int *checksum_str;
int i, code, textpos, checksum_len=0;
int c_checksum = 0;
int k_checksum = 0;
if (bc->partial)
free(bc->partial);
if (bc->textinfo)
free(bc->textinfo);
bc->partial = bc->textinfo = NULL; /* safe */
if (!bc->encoding)
bc->encoding = strdup("code 93");
text = bc->ascii;
if (!text) {
bc->error = EINVAL;
return -1;
}
/* the partial code is 6 * (head + 2* text + 2* check + tail) + margin + term. */
partial = malloc( (strlen(text) *2 + 4) * 6 +2);
if (!partial) {
bc->error = errno;
return -1;
}
checksum_str = (int *)malloc( (strlen(text) + 3) * 2 * sizeof(int));
if (!checksum_str) {
free(partial);
bc->error = errno;
return -1;
}
/* the text information is at most "nnn:fff:c " * strlen +term */
textinfo = malloc(10*strlen(text) + 2);
if (!textinfo) {
bc->error = errno;
free(partial);
free(checksum_str);
return -1;
}
textptr = textinfo;
textpos = 22;
strcpy(partial, "0");
strcat(partial, codeset[START_STOP]);
for (i=0; i<strlen(text); i++) {
c = strchr(alphabet, text[i]);
if (!c) {
/* Encode the shift character */
switch(shiftset[text[i]])
{
case '$':
code = EXTEND_DOLLAR;
break;
case '%':
code = EXTEND_PERCENT;
break;
case '/':
code = EXTEND_SLASH;
break;
case '+':
code = EXTEND_PLUS;
break;
default:
code = 0;
break;
}
strcat(partial, codeset[code]);
checksum_str[checksum_len++] = code;
/* Encode the second character */
code = strchr(alphabet, shiftset2[text[i]]) - alphabet;
strcat(partial, codeset[code]);
checksum_str[checksum_len++] = code;
} else {
/* Character is natively supported by the symbology, encode directly */
code = c - alphabet;
strcat(partial, codeset[c -alphabet]);
checksum_str[checksum_len++] = code;
}
sprintf(textptr, "%i:12:%c ", textpos, text[i]);
textptr += strlen(textptr);
/*
* width of each code is 9; composed codes are 18, but aligning
* the text behind the right bars would be ugly, so use 9 anyways
*/
textpos += 9;
}
c_checksum=0;
k_checksum=0;
/* Add the checksum */
if ( (bc->flags & BARCODE_NO_CHECKSUM)==0 )
{
for(i=1; i<=checksum_len; i++)
{
c_checksum += i * (int)checksum_str[checksum_len - i];
k_checksum += (i+1) * (int)checksum_str[checksum_len - i];
}
c_checksum = c_checksum % 47;
k_checksum += c_checksum;
k_checksum = k_checksum % 47;
strcat(partial, codeset[c_checksum]);
strcat(partial, codeset[k_checksum]);
}
strcat(partial, codeset[START_STOP]); /* end */
/* Encodes final 1-unit width bar to turn the start character into a stop char */
strcat(partial, "1");
bc->partial = partial;
bc->textinfo = textinfo;
return 0;
}
+774
View File
@@ -0,0 +1,774 @@
/*
* ean.c -- encoding for ean, upc and isbn
*
* Copyright (c) 1999 Alessandro Rubini <rubini@gnu.org>
* Copyright (c) 1999 Prosa Srl. <prosa@prosa.it>
* Copyright (c) 2001 Boszormenyi Zoltan <zboszor@mail.externet.hu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "barcode.h"
/*
* IMPORTANT NOTE: if you are reading this file to learn how to add a
* new encoding type, this is the wrong place as there are too many
* special cases. Please refer to code39.c instead. If you want to
* learn how UPC, EAN, ISBN work, on the other hand, I did my best to
* commend things and hope you enjoy it.
*/
/*
* These following static arrays are used to describe the barcode.
*
* The various forms of UPC and EAN are documented as using three
* different alphabets to encode the ten digits. However, each digit
* has exactly one encoding; only, it is sometimes mirrored. Moreover,
* if you represent the width of each symbol (bar/space) instead of
* the sequence of 1's and 0's, you find that even-parity and odd-parity
* encoding are exactly the same. So, here are the digits: */
static char *digits[] = {
"3211","2221","2122","1411","1132",
"1231","1114","1312","1213","3112"};
/*
* What EAN encoding does is adding a leading digit (the 13th digit).
* Such an extra digit is encoded by mirroring three of the six digits that
* appear in the left half of the UPC code. Here how mirroring works:
*/
static char *ean_mirrortab[] = {
"------","--1-11","--11-1","--111-","-1--11",
"-11--1","-111--","-1-1-1","-1-11-","-11-1-"
};
/*
* UPC-E (the 6-digit one), instead, encodes the check character as
* a mirroring of the symbols. This is similar, but the encoding for "0" is
* different (EAN uses no mirroring for "0" to be compatible with UPC).
* The same rule is used for UPC-5 (the supplemental digits for ISBN)
*/
static char *upc_mirrortab[] = {
"---111","--1-11","--11-1","--111-","-1--11",
"-11--1","-111--","-1-1-1","-1-11-","-11-1-"
};
/*
* UPC-E mirroring for encoding "1"
*/
static char *upc_mirrortab1[] = {
"111---","11-1--","11--1-","11---1","1-11--",
"1--11-","1---11","1-1-1-","1-1--1","1--1-1"
};
/* UPC-2 has just two digits to mirror */
static char *upc_mirrortab2[] = {
"11","1-","-1","--"
};
/*
* initial, middle, final guard bars (first symbol is a a space).
* EAN-13 overwrites the first "0" with "9" to make space for the extra digit.
*/
static char *guard[] = {"0a1a","1a1a1","a1a"};
/* initial, final guard bars for UPC-E*/
static char *guardE[] = {"0a1a","1a1a1a"};
/* initial and inter-char guard bars for supplementals (first is space) */
static char *guardS[] = {"9112","11"};
/*
* These functions are shortcuts I use in the encoding engine
*/
static int ean_make_checksum(char *text, int mode)
{
int esum = 0, osum = 0, i;
int even=1; /* last char is even */
if (strchr(text, ' '))
i = strchr(text, ' ') - text; /* end of first part */
else
i = strlen(text); /* end of all */
while (i-- > 0) {
if (even) esum += text[i]-'0';
else osum += text[i]-'0';
even = !even;
}
if (!mode) { /* standard upc/ean checksum */
i = (3*esum + osum) % 10;
return (10-i) % 10; /* complement to 10 */
} else { /* add-5 checksum */
i = (3*esum + 9*osum);
return i%10;
}
}
/*
* Check that the text can be encoded. Returns 0 or -1.
* Accept:
* 13 or 12 digits: EAN-13 w/ or w/o checksum
* or
* 8 or 7 digits: EAN-8 w/ or w/o checksum.
* For both EAN-13 and EAN-8, accept an addon of 2 or 5 digits,
* separated by ' '
*/
int Barcode_ean_verify(unsigned char *text)
{
int i, len0, len, addon;
unsigned char tmp[24], *spc;
len = strlen(text);
spc = strchr(text, ' ');
if (spc) {
len0 = spc - text;
addon = len - len0 - 1;
if (addon != 2 && addon != 5)
return -1;
for (i=len0+1; i<len; i++)
if (!isdigit(text[i]))
return -1;
} else
len0 = len;
for (i=0; i<len0; i++)
if (!isdigit(text[i]))
return -1;
switch (len0) {
case 8:
strncpy(tmp, text, 7);
tmp[7] = '\0';
if (text[7] != (ean_make_checksum(tmp, 0) + '0'))
return -1;
case 7:
break;
case 13:
strncpy(tmp, text, 12);
tmp[12] = '\0';
if (text[12] != (ean_make_checksum(tmp, 0) + '0'))
return -1;
case 12:
break;
default:
return -1;
}
return 0;
}
/* Expand the middle part of UPC-E to UPC-A */
static char *upc_e_to_a0(unsigned char *text)
{
static char result[16];
strcpy(result, "00000000000"); /* 11 0's */
switch(text[5]) { /* last char */
case '0': case '1': case '2':
strncpy(result+1, text, 2); result[3]=text[5]; /* Manuf. */
memcpy(result+8, text+2, 3); /* Product */
break;
case '3':
memcpy(result+1, text, 3); /* Manufacturer */
memcpy(result+9, text+3, 2); /* Product */
break;
case '4':
memcpy(result+1, text, 4); /* Manufacturer */
memcpy(result+10, text+4, 1); /* Product */
break;
default:
memcpy(result+1, text, 5); /* Manufacturer */
memcpy(result+10, text+5, 1); /* Product */
break;
}
return result;
}
/* Try to expand an UPC-E barcode to its UPC-A equivalent.
* Accept 6, 7 or 8-digit sequence (not counting the addon):
* 6: only the middle part, encoding "0", w/o checksum.
* 7: the middle part, encoding "0" with a correct checksum
* or
* the middle part, encoding "0" or "1" prepended
* 8: fully qualified UPC-E with checksum.
*
* Returns a 11 digit UPC-A (w/o checksum) for valid EPC-E barcode
* or an empty string for an invalid one.
*
* The checksum for UPC-E is calculated using its UPC-A equivalent.
*/
static char *upc_e_to_a(unsigned char *text)
{
static unsigned char result[16], *spc;
int len, chk;
spc = strchr(text, ' ');
if (spc)
len = spc - text;
else
len = strlen(text);
switch (len) {
case 6:
strcpy(result, upc_e_to_a0(text));
return result;
case 7:
/* the first char is '0' or '1':
* valid number system for UPC-E and no checksum
*/
if (text[0] == '0' || text[0] == '1') {
strcpy(result, upc_e_to_a0(text+1));
result[0] = text[0];
return result;
}
/* Find out whether the 7th char is correct checksum */
strcpy(result, upc_e_to_a0(text));
chk = ean_make_checksum(result, 0);
if (chk == (text[len-1] - '0'))
return result;
/* Invalid 7 digit representation for UPC-E. */
return NULL;
case 8:
if (text[0] == '0' || text[0] == '1') {
strcpy(result, upc_e_to_a0(text+1));
result[0] = text[0];
chk = ean_make_checksum(result, 0);
if (chk == (text[len-1] - '0'))
return result;
}
default:
/* Invalid representation for UPC-E. */
return NULL;
}
}
/*
* Accept a 11 or 12 digit UPC-A barcode and
* shrink it into an 8-digit UPC-E equivalent if possible.
* Return NULL if impossible, the UPC-E barcode if possible.
*/
static unsigned char *upc_a_to_e(unsigned char *text)
{
static unsigned char result[16];
int len, chksum;
len = strlen(text);
switch (len) {
case 12:
strcpy(result, text);
result[11] = '\0';
chksum = ean_make_checksum(result, 0);
if (text[11] != (chksum - '0'))
return NULL;
break;
case 11:
chksum = ean_make_checksum(text, 0);
break;
default:
return NULL;
}
strcpy(result, "00000000"); /* 8 0's*/
/* UPC-E can only be used with number system 0 or 1 */
if (text[0] != '0' && text[0] != '1')
return NULL;
result[0] = text[0];
if ((text[3] == '0' || text[3] == '1' || text[3] == '2')
&& !strncmp(text+4, "0000", 4)) {
memcpy(&result[1], text+1, 2);
memcpy(&result[3], text+8, 3);
result[6] = text[3];
} else if (!strncmp(text+4, "00000", 5)) {
memcpy(&result[1], text+1, 3);
memcpy(&result[4], text+9, 2);
result[6] = '3';
} else if (!strncmp(text+5, "00000", 5)) {
memcpy(&result[1], text+1, 4);
result[5] = text[10];
result[6] = '4';
} else if ((text[5] != '0') && !strncmp(text+6, "0000", 4)
&& text[10] >= '5' && text[10] <= '9') {
memcpy(&result[1], text+1, 5);
result[6] = text[10];
} else {
return NULL;
}
result[7] = chksum + '0';
return result;
}
/*
* UPC-A is the same as EAN, but accept
* 12 or 11 digits (UPC-A w/ or w/o checksum)
* or accept UPC-E as:
* 6 digits (w/o number system and checksum): number system '0' assumed,
* 7 digits (either w/o number system or checksum),
* 8 digits (w/ number system and checksum)
* plus the 2 or 5-digit add-on
*/
int Barcode_upc_verify(unsigned char *text)
{
int i, len0, len, addon;
unsigned char tmp[24], *spc;
len = strlen(text);
spc = strchr(text, ' ');
if (spc) {
len0 = spc - text;
addon = len - len0 - 1;
if (addon != 2 && addon != 5)
return -1;
for (i=len0+1; i<len; i++)
if (!isdigit(text[i]))
return -1;
} else
len0 = len;
for (i=0; i<len0; i++)
if (!isdigit(text[i]))
return -1;
switch (len0) {
case 6: case 7: case 8:
strncpy(tmp, text, len0);
tmp[len0] = '\0';
if (!upc_e_to_a(tmp))
return -1;
break;
case 12:
strncpy(tmp, text, 11);
tmp[11] = '\0';
if (text[11] != (ean_make_checksum(tmp, 0) + '0'))
return -1;
case 11:
break;
default:
return -1;
}
return 0;
}
/*
* Isbn is the same as EAN, just shorter. Dashes are accepted, the
* check character (if specified) is skipped, the extra 5 digits are
* accepted after a blank.
*/
int Barcode_isbn_verify(unsigned char *text)
{
int i, ndigit=0;
for (i=0; text[i]; i++) {
if (text[i] == '-')
continue;
if (isdigit(text[i])) {
ndigit++;
if (ndigit == 9) { /* got it all */
i++; break;
}
continue;
}
return -1; /* found non-digit */
}
if (ndigit!=9) return -1; /* too short */
/* skip an hyphen, if any */
if (text[i] == '-')
i++;
/* accept one more char if any (the checksum) */
if (isdigit(text[i]) || toupper(text[i])=='X')
i++;
if (text[i] == '\0')
return 0; /* Ok */
/* and accept the extra price tag (blank + 5 digits), if any */
if (strlen(text+i) != 6)
return -1;
if (text[i] != ' ')
return -1;
i++; /* skip the blank */
while (text[i]) {
if (!isdigit(text[i]))
return -1;
i++;
}
return 0; /* Ok: isbn + 5-digit addon */
}
static int width_of_partial(unsigned char *partial)
{
int i=0;
while (*partial) {
if (isdigit(*partial))
i += *partial - '0';
else if (islower(*partial))
i += *partial - 'a' + 1;
partial++;
}
return i;
}
/*
* The encoding functions fills the "partial" and "textinfo" fields.
* This one deals with both upc (-A and -E) and ean (13 and 8).
*/
int Barcode_ean_encode(struct Barcode_Item *bc)
{
static char text[24];
static char partial[256];
static char textinfo[256];
char *mirror, *ptr1, *ptr2, *tptr = textinfo; /* where text is written */
char *spc;
enum {UPCA, UPCE, EAN13, EAN8, ISBN} encoding = ISBN;
int i, xpos, checksum, len, len0, addon;
if (!bc->ascii) {
bc->error = EINVAL;
return -1;
}
/* Find out whether the barcode has addon and
* the length of the barcode w/o the addon.
*/
len = strlen(bc->ascii);
spc = strchr(bc->ascii, ' ');
if (spc) {
len0 = spc - bc->ascii;
addon = strlen(spc + 1);
if (addon != 2 && addon != 5) {
bc->error = EINVAL; /* impossible, actually */
return -1;
}
} else {
len0 = len;
addon = 0;
}
if (!bc->encoding) {
/* ISBN already wrote what it is; if unknown, find it out */
/*
* Do not decide only by barcode length, it may be ambiguous.
* Anyway, either the user specified the barcode type or
* we already found a fitting one.
*/
switch(bc->flags & BARCODE_ENCODING_MASK) {
case BARCODE_EAN:
switch (len0) {
case 7: case 8:
bc->encoding = strdup("EAN-8");
encoding = EAN8;
break;
case 12: case 13:
bc->encoding = strdup("EAN-13");
encoding = EAN13;
break;
default:
bc->error = -EINVAL;
return -1;
}
break;
case BARCODE_UPC:
switch (len0) {
case 6: case 7: case 8:
bc->encoding = strdup("UPC-E");
encoding = UPCE;
break;
case 11: case 12:
bc->encoding = strdup("UPC-A");
encoding = UPCA;
break;
default:
bc->error = -EINVAL;
return -1;
}
break;
default:
/* else, it's wrong (impossible, as the text is checked) */
bc->error = -EINVAL;
return -1;
}
}
/* better safe than sorry */
if (bc->partial) free(bc->partial); bc->partial = NULL;
if (bc->textinfo) free(bc->textinfo); bc->textinfo = NULL;
if (encoding == UPCA) { /* add the leading 0 (not printed) */
text[0] = '0';
strcpy(text+1, bc->ascii);
} else if (encoding == UPCE) {
strcpy(text, upc_a_to_e(upc_e_to_a(bc->ascii)));
} else {
strcpy(text, bc->ascii);
}
/*
* build the checksum and the bars: any encoding is slightly different
*/
if (encoding == UPCA || encoding == EAN13 || encoding == ISBN) {
if (!(encoding == UPCA && len0 == 12) &&
!(encoding == EAN13 && len0 == 13)) {
checksum = ean_make_checksum(text, 0);
text[12] = '0' + checksum; /* add it to the text */
text[13] = '\0';
}
strcpy(partial, guard[0]);
if (encoding == EAN13 || encoding == ISBN) { /* The first digit */
sprintf(tptr,"0:12:%c ",text[0]);
tptr += strlen(tptr);
partial[0] = '9'; /* extra space for the digit */
} else if (encoding == UPCA)
partial[0] = '9'; /* UPC has one digit before the symbol, too */
xpos = width_of_partial(partial);
mirror = ean_mirrortab[text[0]-'0'];
/* left part */
for (i=1;i<7;i++) {
ptr1 = partial + strlen(partial); /* target */
ptr2 = digits[text[i]-'0']; /* source */
strcpy(ptr1, ptr2);
if (mirror[i-1] == '1') {
/* mirror this */
ptr1[0] = ptr2[3];
ptr1[1] = ptr2[2];
ptr1[2] = ptr2[1];
ptr1[3] = ptr2[0];
}
/*
* Write the ascii digit. UPC has a special case
* for the first digit, which is out of the bars
*/
if (encoding == UPCA && i==1) {
sprintf(tptr, "0:10:%c ", text[i]);
tptr += strlen(tptr);
ptr1[1] += 'a'-'1'; /* bars are long */
ptr1[3] += 'a'-'1';
} else {
sprintf(tptr, "%i:12:%c ", xpos, text[i]);
tptr += strlen(tptr);
}
/* count the width of the symbol */
xpos += 7; /* width_of_partial(ptr2) */
}
strcat(partial, guard[1]); /* middle */
xpos += width_of_partial(guard[1]);
/* right part */
for (i=7;i<13;i++) {
ptr1 = partial + strlen(partial); /* target */
ptr2 = digits[text[i]-'0']; /* source */
strcpy(ptr1, ptr2);
/*
* Ascii digit. Once again, UPC has a special
* case for the last digit
*/
if (encoding == UPCA && i==12) {
sprintf(tptr, "%i:10:%c ", xpos+13, text[i]);
tptr += strlen(tptr);
ptr1[0] += 'a'-'1'; /* bars are long */
ptr1[2] += 'a'-'1';
} else {
sprintf(tptr, "%i:12:%c ", xpos, text[i]);
tptr += strlen(tptr);
}
xpos += 7; /* width_of_partial(ptr2) */
}
tptr[-1] = '\0'; /* overwrite last space */
strcat(partial, guard[2]); /* end */
xpos += width_of_partial(guard[2]);
} else if (encoding == UPCE) {
checksum = text[7] - '0';
strcpy(partial, guardE[0]);
partial[0] = '9'; /* UPC-A has one digit before the symbol, too */
xpos = width_of_partial(partial);
/* UPC-E has the number system written before the bars. */
sprintf(tptr, "0:10:%c ", text[0]);
tptr += strlen(tptr);
if (text[0] == '0')
mirror = upc_mirrortab[checksum];
else
mirror = upc_mirrortab1[checksum];
for (i=0;i<6;i++) {
ptr1 = partial + strlen(partial); /* target */
ptr2 = digits[text[i+1]-'0']; /* source */
strcpy(ptr1, ptr2);
if (mirror[i] != '1') { /* negated wrt EAN13 */
/* mirror this */
ptr1[0] = ptr2[3];
ptr1[1] = ptr2[2];
ptr1[2] = ptr2[1];
ptr1[3] = ptr2[0];
}
sprintf(tptr, "%i:12:%c ", xpos, text[i+1]);
tptr += strlen(tptr);
xpos += 7; /* width_of_partial(ptr2) */
}
sprintf(tptr, "%i:10:%c ", xpos+10, text[7]);
tptr += strlen(tptr);
ptr1[0] += 'a'-'1'; /* bars are long */
ptr1[2] += 'a'-'1';
tptr[-1] = '\0'; /* overwrite last space */
strcat(partial, guardE[1]); /* end */
} else { /* EAN-8 almost identical to EAN-13 but no mirroring */
if (len0 != 8) {
checksum = ean_make_checksum(text, 0);
text[7] = '0' + checksum; /* add it to the text */
text[8] = '\0';
}
strcpy(partial, guard[0]);
xpos = width_of_partial(partial);
/* left part */
for (i=0;i<4;i++) {
strcpy(partial + strlen(partial), digits[text[i]-'0']);
sprintf(tptr, "%i:12:%c ", xpos, text[i]);
tptr += strlen(tptr);
xpos += 7; /* width_of_partial(digits[text[i]-'0' */
}
strcat(partial, guard[1]); /* middle */
xpos += width_of_partial(guard[1]);
/* right part */
for (i=4;i<8;i++) {
strcpy(partial + strlen(partial), digits[text[i]-'0']);
sprintf(tptr, "%i:12:%c ", xpos, text[i]);
tptr += strlen(tptr);
xpos += 7; /* width_of_partial(digits[text[i]-'0' */
}
tptr[-1] = '\0'; /* overwrite last space */
strcat(partial, guard[2]); /* end */
}
/*
* And that's it. Now, in case some add-on is specified it
* must be encoded too. Look for it.
*/
if ( (ptr1 = spc) ) {
ptr1++;
strcpy(text, ptr1);
if (strlen(ptr1)==5) {
checksum = ean_make_checksum(text, 1 /* special way */);
mirror = upc_mirrortab[checksum]+1; /* only last 5 digits */
} else {
checksum = atoi(text)%4;
mirror = upc_mirrortab2[checksum];
}
strcat(textinfo, " +"); strcat(partial, "+");
tptr = textinfo + strlen(textinfo);
for (i=0; i<strlen(text); i++) {
if (!i) {
strcat(partial, guardS[0]); /* separation and head */
xpos += width_of_partial(guardS[0]);
} else {
strcat(partial, guardS[1]);
xpos += width_of_partial(guardS[1]);
}
ptr1 = partial + strlen(partial); /* target */
ptr2 = digits[text[i]-'0']; /* source */
strcpy(ptr1, ptr2);
if (mirror[i] != '1') { /* negated wrt EAN13 */
/* mirror this */
ptr1[0] = ptr2[3];
ptr1[1] = ptr2[2];
ptr1[2] = ptr2[1];
ptr1[3] = ptr2[0];
}
/* and the text */
sprintf(tptr, " %i:12:%c", xpos, text[i]);
tptr += strlen(tptr);
xpos += 7; /* width_of_partial(ptr2) */
}
}
/* all done, copy results to the data structure */
bc->partial = strdup(partial);
if (!bc->partial) {
bc->error = errno;
return -1;
}
bc->textinfo = strdup(textinfo);
if (!bc->textinfo) {
bc->error = errno;
free(bc->partial);
bc->partial = NULL;
return -1;
}
if (!bc->width)
bc->width = width_of_partial(partial);
return 0; /* success */
}
int Barcode_upc_encode(struct Barcode_Item *bc)
{
return Barcode_ean_encode(bc); /* UPC is folded into EAN */
}
int Barcode_isbn_encode(struct Barcode_Item *bc)
{
/* For ISBN we must normalize the string and prefix "978" */
unsigned char *text = malloc(24); /* 13 + ' ' + 5 plus some slack */
unsigned char *otext;
int i, j, retval;
if (!text) {
bc->error = ENOMEM;
return -1;
}
strcpy(text, "978"); j=3;
otext = bc->ascii;
for (i=0; otext[i]; i++) {
if (isdigit(otext[i]))
text[j++] = otext[i];
if (j == 12) /* checksum added later */
break;
}
text[j]='\0';
if (strchr(otext, ' '))
strcat(text, strchr(otext, ' '));
bc->ascii = text;
bc->encoding = strdup("ISBN");
retval = Barcode_ean_encode(bc);
bc->ascii = otext; /* restore ascii for the ps comments */
free(text);
return retval;
}
+164
View File
@@ -0,0 +1,164 @@
/*
* i25.c -- "interleaved 2 of 5"
*
* Copyright (c) 1999,2000 Alessandro Rubini (rubini@gnu.org)
* Copyright (c) 1999 Prosa Srl. (prosa@prosa.it)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "barcode.h"
static char *codes[] = {
"11331", "31113", "13113", "33111", "11313",
"31311", "13311", "11133", "31131", "13131"
};
static char *guard[] = {"a1a1", "c1a"}; /* begin end */
int Barcode_i25_verify(unsigned char *text)
{
if (!text[0])
return -1;
while (*text && isdigit(*text))
text++;
if (*text)
return -1; /* a non-digit char */
return 0; /* ok */
}
int Barcode_i25_encode(struct Barcode_Item *bc)
{
unsigned char *text;
unsigned char *partial; /* dynamic */
unsigned char *textinfo; /* dynamic */
unsigned char *textptr, *p1, *p2, *pd;
int i, len, sum[2], textpos, usesum = 0;
if (bc->partial)
free(bc->partial);
if (bc->textinfo)
free(bc->textinfo);
bc->partial = bc->textinfo = NULL; /* safe */
if (!bc->encoding)
bc->encoding = strdup("interleaved 2 of 5");
text = bc->ascii;
if (!bc->ascii) {
bc->error = EINVAL;
return -1;
}
if ((bc->flags & BARCODE_NO_CHECKSUM)) usesum = 0; else usesum = 1;
/* create the real text string, padded to an even number of digits */
text = malloc(strlen(bc->ascii) + 3); /* leading 0, checksum, term. */
if (!text) {
bc->error = errno;
return -1;
}
/* add the leading 0 if needed */
i = strlen(bc->ascii) + usesum;
if (i % 2) {
/* add a leading 0 */
text[0] = '0';
strcpy(text+1, bc->ascii);
} else {
strcpy(text, bc->ascii);
}
/* add the trailing checksum if needed, the leading 0 is ignored */
if (usesum) {
sum[0] = sum[1] = 0;
for (i=0; text[i]; i++)
sum[i%2] += text[i]-'0';
/*
* The "even" sum must be multiplied by three, and the *
* rightmost digit is defined as "even". The digits' position
* is already correct, whether or not we added a leading zero.
* (e.g., they are in pos. 0..4 or 1..4 of the string)
*/
i = sum[0] * 3 + sum[1];
strcat(text, "0");
text[strlen(text)-1] += (10 - (i%10)) % 10;
}
/* the partial code is 5 * (text + check) + 4(head) + 3(tail) + term. */
partial = malloc( (strlen(text) + 3) * 5 +2); /* be large... */
if (!partial) {
bc->error = errno;
free(text);
return -1;
}
/* the text information is at most "nnn:fff:c " * (strlen+1) +term */
textinfo = malloc(10*(strlen(text)+1) + 2);
if (!textinfo) {
bc->error = errno;
free(partial);
free(text);
return -1;
}
strcpy(partial, "0"); /* the first space */
strcat(partial, guard[0]); /* start */
textpos = 4; /* width of initial guard */
textptr = textinfo;
len = strlen(text);
for (i=0; i<len; i+=2) {
if (!isdigit(text[i]) || !isdigit(text[i+1])) {
bc->error = EINVAL; /* impossible if text is verified */
free(partial);
free(textinfo);
free(text);
return -1;
}
/* interleave two digits */
p1 = codes[text[i]-'0'];
p2 = codes[text[i+1]-'0'];
pd = partial + strlen(partial); /* destination */
while (*p1) {
*(pd++) = *(p1++);
*(pd++) = *(p2++);
}
*pd = '\0';
/* and print the ascii text (but don't print the checksum, if any */
if (usesum && strlen(text+i)==2) {
/* print only one digit, discard the checksum */
sprintf(textptr, "%i:12:%c ", textpos, text[i]);
} else {
sprintf(textptr, "%i:12:%c %i:12:%c ", textpos, text[i],
textpos+9, text[i+1]);
}
textpos += 18; /* width of two codes */
textptr += strlen(textptr);
}
strcat(partial, guard[1]);
bc->partial = partial;
bc->textinfo = textinfo;
free(text);
return 0;
}
+247
View File
@@ -0,0 +1,247 @@
/*
* library.c -- external functions of libbarcode
*
* Copyright (c) 1999 Alessandro Rubini (rubini@gnu.org)
* Copyright (c) 1999 Prosa Srl. (prosa@prosa.it)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_UNISTD_H /* sometimes (windows, for instance) it's missing */
# include <unistd.h>
#endif
#include <errno.h>
#include "barcode.h"
//#include "QFile.h"
//#include "QString.h"
/*
* This function allocates a barcode structure and strdup()s the
* text string. It returns NULL in case of error
*/
struct Barcode_Item *Barcode_Create(char *text)
{
struct Barcode_Item *bc;
bc = malloc(sizeof(*bc));
if (!bc) return NULL;
memset(bc, 0, sizeof(*bc));
bc->ascii = strdup(text);
bc->margin = BARCODE_DEFAULT_MARGIN; /* default margin */
return bc;
}
/*
* Free a barcode structure
*/
int Barcode_Delete(struct Barcode_Item *bc)
{
if (bc->ascii)
free(bc->ascii);
if (bc->partial)
free(bc->partial);
if (bc->textinfo)
free(bc->textinfo);
if (bc->encoding)
free(bc->encoding);
free(bc);
return 0; /* always success */
}
/*
* The various supported encodings. This might be extended to support
* dynamic addition of extra encodings
*/
extern int Barcode_ean_verify(unsigned char *text);
extern int Barcode_ean_encode(struct Barcode_Item *bc);
extern int Barcode_upc_verify(unsigned char *text);
extern int Barcode_upc_encode(struct Barcode_Item *bc);
extern int Barcode_isbn_verify(unsigned char *text);
extern int Barcode_isbn_encode(struct Barcode_Item *bc);
extern int Barcode_39_verify(unsigned char *text);
extern int Barcode_39_encode(struct Barcode_Item *bc);
extern int Barcode_128b_verify(unsigned char *text);
extern int Barcode_128b_encode(struct Barcode_Item *bc);
extern int Barcode_128c_verify(unsigned char *text);
extern int Barcode_128c_encode(struct Barcode_Item *bc);
extern int Barcode_128_verify(unsigned char *text);
extern int Barcode_128_encode(struct Barcode_Item *bc);
extern int Barcode_128raw_verify(unsigned char *text);
extern int Barcode_128raw_encode(struct Barcode_Item *bc);
extern int Barcode_i25_verify(unsigned char *text);
extern int Barcode_i25_encode(struct Barcode_Item *bc);
extern int Barcode_cbr_verify(unsigned char *text);
extern int Barcode_cbr_encode(struct Barcode_Item *bc);
extern int Barcode_msi_verify(unsigned char *text);
extern int Barcode_msi_encode(struct Barcode_Item *bc);
extern int Barcode_pls_verify(unsigned char *text);
extern int Barcode_pls_encode(struct Barcode_Item *bc);
extern int Barcode_93_verify(unsigned char *text);
extern int Barcode_93_encode(struct Barcode_Item *bc);
struct encoding {
int type;
int (*verify)(unsigned char *text);
int (*encode)(struct Barcode_Item *bc);
};
struct encoding encodings[] = {
{BARCODE_EAN, Barcode_ean_verify, Barcode_ean_encode},
{BARCODE_UPC, Barcode_upc_verify, Barcode_upc_encode},
{BARCODE_ISBN, Barcode_isbn_verify, Barcode_isbn_encode},
{BARCODE_128B, Barcode_128b_verify, Barcode_128b_encode},
{BARCODE_128C, Barcode_128c_verify, Barcode_128c_encode},
{BARCODE_128RAW, Barcode_128raw_verify, Barcode_128raw_encode},
{BARCODE_39, Barcode_39_verify, Barcode_39_encode},
{BARCODE_I25, Barcode_i25_verify, Barcode_i25_encode},
{BARCODE_128, Barcode_128_verify, Barcode_128_encode},
{BARCODE_CBR, Barcode_cbr_verify, Barcode_cbr_encode},
{BARCODE_PLS, Barcode_pls_verify, Barcode_pls_encode},
{BARCODE_MSI, Barcode_msi_verify, Barcode_msi_encode},
{BARCODE_93, Barcode_93_verify, Barcode_93_encode},
{0, NULL, NULL}
};
/*
* A function to encode a string into bc->partial, ready for
* postprocessing to the output file. Meaningful bits for "flags" are
* the encoding mask and the no-checksum flag. These bits
* get saved in the data structure.
*/
int Barcode_Encode(struct Barcode_Item *bc, int flags)
{
int validbits = BARCODE_ENCODING_MASK | BARCODE_NO_CHECKSUM;
struct encoding *cptr;
/* If any flag is cleared in "flags", inherit it from "bc->flags" */
if (!(flags & BARCODE_ENCODING_MASK))
flags |= bc->flags & BARCODE_ENCODING_MASK;
if (!(flags & BARCODE_NO_CHECKSUM))
flags |= bc->flags & BARCODE_NO_CHECKSUM;
flags = bc->flags = (flags & validbits) | (bc->flags & ~validbits);
if (!(flags & BARCODE_ENCODING_MASK)) {
/* get the first code able to handle the text */
for (cptr = encodings; cptr->verify; cptr++)
if (cptr->verify((unsigned char *)bc->ascii)==0)
break;
if (!cptr->verify) {
bc->error = EINVAL; /* no code can handle this text */
return -1;
}
flags |= cptr->type; /* this works */
bc->flags |= cptr->type;
}
for (cptr = encodings; cptr->verify; cptr++)
if (cptr->type == (flags & BARCODE_ENCODING_MASK))
break;
if (!cptr->verify) {
bc->error = EINVAL; /* invalid barcode type */
return -1;
}
if (cptr->verify(bc->ascii) != 0) {
bc->error = EINVAL;
return -1;
}
return cptr->encode(bc);
}
/*
* When multiple output formats are supported, there will
* be a jumpt table like the one for the types. Now we don't need it
*/
extern int Barcode_ps_print(struct Barcode_Item *bc, FILE *f);
extern int Barcode_pcl_print(struct Barcode_Item *bc, FILE *f);
/*
* A function to print a partially decoded string. Meaningful bits for
* "flags" are the output mask etc. These bits get saved in the data
* structure.
*/
int Barcode_Print(struct Barcode_Item *bc, FILE *f, int flags)
{
int validbits = BARCODE_OUTPUT_MASK | BARCODE_NO_ASCII
| BARCODE_OUT_NOHEADERS;
/* If any flag is clear in "flags", inherit it from "bc->flags" */
if (!(flags & BARCODE_OUTPUT_MASK))
flags |= bc->flags & BARCODE_OUTPUT_MASK;
if (!(flags & BARCODE_NO_ASCII))
flags |= bc->flags & BARCODE_NO_ASCII;
if (!(flags & BARCODE_OUT_NOHEADERS))
flags |= bc->flags & BARCODE_OUT_NOHEADERS;
flags = bc->flags = (flags & validbits) | (bc->flags & ~validbits);
if (bc->flags & BARCODE_OUT_PCL)
return Barcode_pcl_print(bc, f);
return Barcode_ps_print(bc, f);
}
/*
* Choose the position
*/
int Barcode_Position(struct Barcode_Item *bc, int wid, int hei,
int xoff, int yoff, double scalef)
{
bc->width = wid; bc->height = hei;
bc->xoff = xoff; bc->yoff = yoff;
bc->scalef = scalef;
return 0;
}
/*
* Do it all in one step
*/
int Barcode_Encode_and_Print(char *text, FILE *f, int wid, int hei,
int xoff, int yoff, int flags)
{
struct Barcode_Item * bc;
if (!(bc=Barcode_Create(text))) {
errno = -ENOMEM;
return -1;
}
if ( Barcode_Position(bc, wid, hei, xoff, yoff, 0.0) < 0
|| Barcode_Encode(bc, flags) < 0
|| Barcode_Print(bc, f, flags) < 0) {
errno = bc->error;
Barcode_Delete(bc);
return -1;
}
Barcode_Delete(bc);
return 0;
}
/*
* Return the version
*/
int Barcode_Version(char *vptr)
{
if (vptr)
strcpy(vptr, BARCODE_VERSION);
return BARCODE_VERSION_INT;
}
+155
View File
@@ -0,0 +1,155 @@
/*
* msi.c -- encoding for MSI-Plessey
*
* Copyright (c) 2000 Leonid A. Broukhis (leob@mailcom.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "barcode.h"
/* Patterns */
static char *patterns[] = { "13", "31" };
static char *fillers[] = { "031", "131" };
static int width = 16 /* each character uses 4 patterns */,
startpos = 6 /* length of the first filler */;
/*
* Check that the text can be encoded. Returns 0 or -1.
*/
int Barcode_msi_verify(unsigned char *text)
{
int i;
if (!strlen(text))
return -1;
for (i=0; text[i]; i++) {
if (!isdigit(text[i]))
return -1;
}
return 0;
}
static int add_one(char *ptr, int code)
{
sprintf(ptr, "%s%s%s%s",
patterns[(code >> 3) & 1],
patterns[(code >> 2) & 1],
patterns[(code >> 1) & 1],
patterns[code & 1]);
return 0;
}
/*
* The encoding functions fills the "partial" and "textinfo" fields.
* Lowercase chars are converted to uppercase
*/
int Barcode_msi_encode(struct Barcode_Item *bc)
{
static char *text;
static char *partial; /* dynamic */
static char *textinfo; /* dynamic */
char *ptr, *textptr;
int i, code, textpos, usesum, checksum = 0;
if (bc->partial)
free(bc->partial);
if (bc->textinfo)
free(bc->textinfo);
bc->partial = bc->textinfo = NULL; /* safe */
if (!bc->encoding)
bc->encoding = strdup("msi");
if ((bc->flags & BARCODE_NO_CHECKSUM))
usesum = 0;
else
usesum = 1;
text = bc->ascii;
/* the partial code is head + 8 * (text + check) + tail + margin + term. */
partial = malloc( 3 + 8 * (strlen(text) + 1) + 3 + 2 );
if (!partial) {
bc->error = errno;
return -1;
}
/* the text information is at most "nnn:fff:c " * strlen +term */
textinfo = malloc(10*strlen(text) + 2);
if (!textinfo) {
bc->error = errno;
free(partial);
return -1;
}
strcpy(partial, fillers[0]);
ptr = partial + strlen(partial);
textptr = textinfo;
textpos = startpos;
for (i=0; i<strlen(text); i++) {
code = text[i] - '0';
add_one(ptr, code);
sprintf(textptr, "%i:12:%c ", textpos, text[i]);
textpos += width; /* width of each code */
textptr += strlen(textptr);
ptr += strlen(ptr);
if (usesum) {
/* For a code ...FEDCBA the checksum is computed
* as the sum of digits of the number ...FDB plus
* the sum of digits of the number ...ECA * 2.
* Which is equivalent to the sum of each digit of ...ECA doubled
* plus carry.
*/
if ((i ^ strlen(text)) & 1) {
/* a last digit, 2 away from last, etc. */
checksum += 2 * code + (2 * code) / 10;
} else {
checksum += code;
}
}
}
/* Some implementations use a double checksum. Currently the only way
* to print a barcode with double checksum is to put the checksum
* digit printed below at the end of a code in the command line
* and re-run the program.
*/
if (usesum) {
/* the check digit is the complement of the checksum
* to a multiple of 10.
*/
checksum = (checksum + 9) / 10 * 10 - checksum;
/* fprintf(stderr, "Checksum: %d\n", checksum); */
add_one(ptr, checksum);
ptr += strlen(ptr);
}
strcpy(ptr, fillers[1]);
bc->partial = partial;
bc->textinfo = textinfo;
return 0;
}
+200
View File
@@ -0,0 +1,200 @@
/*
* pcl.c -- printing the "partial" bar encoding in PCL format
*
* Copyright (c) 1999 Alessandro Rubini (rubini@gnu.org)
* Copyright (c) 1999 Prosa Srl. (prosa@prosa.it)
* Copyright (c) 2001 Andrea Scopece (a.scopece@tin.it)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "barcode.h"
#define SHRINK_AMOUNT 0.15 /* shrink the bars to account for ink spreading */
/*
* How do the "partial" and "textinfo" strings work? See file "ps.c"
*/
int Barcode_pcl_print(struct Barcode_Item *bc, FILE *f)
{
int i, j, k, barlen;
double f1, f2, fsav=0;
int mode = '-'; /* text below bars */
double scalef=1, xpos, x0, y0, yr;
unsigned char *ptr;
unsigned char c;
char font_id[6]; /* default font, should be "scalable" */
/* 0 Line printer, use on older LJet II, isn't scalable */
/* 4148 Univers, use on LJet III series, and Lj 4L, 5L */
/* 16602 Arial, default LJ family 4, 5, 6, Color, Djet */
if (!bc->partial || !bc->textinfo) {
bc->error = EINVAL;
return -1;
}
/*
* Maybe this first part can be made common to several printing back-ends,
* we'll see how that works when other ouput engines are added
*/
/* First, calculate barlen */
barlen = bc->partial[0] - '0';
for (ptr = bc->partial+1; *ptr; ptr++)
if (isdigit(*ptr))
barlen += (*ptr - '0');
else if (islower(*ptr))
barlen += (*ptr - 'a'+1);
/* The scale factor depends on bar length */
if (!bc->scalef) {
if (!bc->width) bc->width = barlen; /* default */
scalef = bc->scalef = (double)bc->width / (double)barlen;
}
/* The width defaults to "just enough" */
if (!bc->width) bc->width = barlen * scalef +1;
/* But it can be too small, in this case enlarge and center the area */
if (bc->width < barlen * scalef) {
int wid = barlen * scalef + 1;
bc->xoff -= (wid - bc->width)/2 ;
bc->width = wid;
/* Can't extend too far on the left */
if (bc->xoff < 0) {
bc->width += -bc->xoff;
bc->xoff = 0;
}
}
/* The height defaults to 80 points (rescaled) */
if (!bc->height) bc->height = 80 * scalef;
#if 0
/* If too small (5 + text), enlarge and center */
i = 5 + 10 * ((bc->flags & BARCODE_NO_ASCII)==0);
if (bc->height < i * scalef ) {
int hei = i * scalef;
bc->yoff -= (hei-bc->height)/2;
bc->height = hei;
if (bc->yoff < 0) {
bc->height += -bc->yoff;
bc->yoff = 0;
}
}
#else
/* If too small (5 + text), reduce the scale factor and center */
i = 5 + 10 * ((bc->flags & BARCODE_NO_ASCII)==0);
if (bc->height < i * scalef ) {
double scaleg = ((double)bc->height) / i;
int wid = bc->width * scaleg / scalef;
bc->xoff += (bc->width - wid)/2;
bc->width = wid;
scalef = scaleg;
}
#endif
/*
* deal with PCL output
*/
xpos = bc->margin + (bc->partial[0]-'0') * scalef;
for (ptr = bc->partial+1, i=1; *ptr; ptr++, i++) {
/* special cases: '+' and '-' */
if (*ptr == '+' || *ptr == '-') {
mode = *ptr; /* don't count it */ i++; continue;
}
/* j is the width of this bar/space */
if (isdigit (*ptr)) j = *ptr-'0';
else j = *ptr-'a'+1;
if (i%2) { /* bar */
x0 = bc->xoff + xpos;
y0 = bc->yoff + bc->margin;
yr = bc->height;
if (!(bc->flags & BARCODE_NO_ASCII)) { /* leave space for text */
if (mode == '-') {
/* text below bars: 10 points or five points */
yr -= (isdigit(*ptr) ? 10 : 5) * scalef;
} else { /* '+' */
/* text above bars: 10 or 0 from bottom, and 10 from top */
y0 += (isdigit(*ptr) ? 10 : 0) * scalef;
yr -= (isdigit(*ptr) ? 20 : 10) * scalef;
}
}
fprintf(f,"%c&a%.0fH", 27, x0 * 10.0);
fprintf(f,"%c&a%.0fV", 27, y0 * 10.0);
fprintf(f,"%c*c%.0fH", 27, ((j*scalef)-SHRINK_AMOUNT) * 10.0);
fprintf(f,"%c*c%.0fV", 27, yr * 10.0);
fprintf(f,"%c*c0P\n", 27);
}
xpos += j * scalef;
}
/* the text */
mode = '-'; /* reinstantiate default */
if (!(bc->flags & BARCODE_NO_ASCII)) {
k=0; /* k is the "previous font size" */
for (ptr = bc->textinfo; ptr; ptr = strchr(ptr, ' ')) {
while (*ptr == ' ') ptr++;
if (!*ptr) break;
if (*ptr == '+' || *ptr == '-') {
mode = *ptr; continue;
}
if (sscanf(ptr, "%lf:%lf:%c", &f1, &f2, &c) != 3) {
fprintf(stderr, "barcode: impossible data: %s\n", ptr);
continue;
}
/* select a Scalable Font */
if (fsav != f2)
{
if ((bc->flags & BARCODE_OUT_PCL_III) == BARCODE_OUT_PCL_III)
{ strcpy(font_id, "4148"); /* font Univers */
}
else
{ strcpy(font_id, "16602"); /* font Arial */
}
fprintf(f,"%c(8U%c(s1p%5.2fv0s0b%sT", 27, 27, f2 * scalef, font_id);
}
fsav = f2;
fprintf(f,"%c&a%.0fH", 27, (bc->xoff + f1 * scalef + bc->margin) * 10.0);
fprintf(f,"%c&a%.0fV", 27,
mode != '-'
? ((double)bc->yoff + bc->margin + 8*scalef) * 10.0
: ((double)bc->yoff + bc->margin + bc->height ) * 10.0);
fprintf(f, "%c", c);
}
}
return 0;
}
+164
View File
@@ -0,0 +1,164 @@
/*
* plessey.c -- encoding for Plessey
*
* Copyright (c) 2000 Leonid A. Broukhis (leob@mailcom.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "barcode.h"
static char * patterns[] = { "13", "31" };
/* this is ordered in decades to simplify encoding */
static char alphabet[] =
"0123456789" "ABCDEF";
/* stop sequence may be 231311313 (barcodemill.com) */
static char *fillers[] = { "031311331", "331311313" };
static int width = 16, startpos = 16;
/*
* Check that the text can be encoded. Returns 0 or -1.
* If it's all lowecase convert to uppercase and accept it
*/
int Barcode_pls_verify(unsigned char *text)
{
int i, upper = 0, lower = 0;
if (!strlen(text))
return -1;
for (i=0; text[i]; i++) {
if (!strchr(alphabet,toupper(text[i])))
return -1;
if (isupper(text[i])) upper++;
if (islower(text[i])) lower++;
}
if (upper && lower)
return -1;
return 0;
}
static int add_one(char *ptr, int code)
{
sprintf(ptr, "%s%s%s%s",
patterns[code & 1],
patterns[(code >> 1) & 1],
patterns[(code >> 2) & 1],
patterns[(code >> 3) & 1]
);
return 0;
}
/*
* The encoding functions fills the "partial" and "textinfo" fields.
* Lowercase chars are converted to uppercase
*/
int Barcode_pls_encode(struct Barcode_Item *bc)
{
static char *text;
static char *partial; /* dynamic */
static char *textinfo; /* dynamic */
char *c, *ptr, *textptr;
unsigned char *checkptr;
int i, code, textpos;
static char check[9] = {1,1,1,1,0,1,0,0,1};
if (bc->partial)
free(bc->partial);
if (bc->textinfo)
free(bc->textinfo);
bc->partial = bc->textinfo = NULL; /* safe */
if (!bc->encoding)
bc->encoding = strdup("plessey");
text = bc->ascii;
if (!text) {
bc->error = EINVAL;
return -1;
}
/* the partial code is 8 * (head + text + check + tail) + margin + term. */
partial = malloc( (strlen(text) + 4) * 8 + 3);
checkptr = calloc (1, strlen(text) * 4 + 8);
if (!partial || !checkptr) {
if (partial) free(partial);
if (checkptr) free(checkptr);
bc->error = errno;
return -1;
}
/* the text information is at most "nnn:fff:c " * strlen +term */
textinfo = malloc(10*strlen(text) + 2);
if (!textinfo) {
bc->error = errno;
free(partial);
return -1;
}
strcpy(partial, fillers[0]);
ptr = partial + strlen(partial);
textptr = textinfo;
textpos = startpos;
for (i=0; i<strlen(text); i++) {
c = strchr(alphabet, toupper(text[i]));
if (!c) {
bc->error = EINVAL; /* impossible if text is verified */
free(partial);
free(textinfo);
return -1;
}
code = c - alphabet;
add_one(ptr, code);
sprintf(textptr, "%i:12:%c ", textpos, toupper(text[i]));
textpos += width; /* width of each code */
textptr += strlen(textptr);
ptr += strlen(ptr);
checkptr[4*i] = code & 1;
checkptr[4*i+1] = (code >> 1) & 1;
checkptr[4*i+2] = (code >> 2) & 1;
checkptr[4*i+3] = (code >> 3) & 1;
}
/* The CRC checksum is required */
for (i=0; i < 4*strlen(text); i++) {
int j;
if (checkptr[i])
for (j = 0; j < 9; j++)
checkptr[i+j] ^= check[j];
}
for (i = 0; i < 8; i++) {
sprintf(ptr, patterns[checkptr[strlen(text) * 4 + i]]);
ptr += 2;
}
fprintf(stderr, "CRC: ");
for (i = 0; i < 8; i++) {
fputc('0' + checkptr[strlen(text) * 4 + i], stderr);
}
fputc('\n', stderr);
strcpy(ptr, fillers[1]);
bc->partial = partial;
bc->textinfo = textinfo;
return 0;
}
+273
View File
@@ -0,0 +1,273 @@
/*
* ps.c -- printing the "partial" bar encoding
*
* Copyright (c) 1999 Alessandro Rubini (rubini@gnu.org)
* Copyright (c) 1999 Prosa Srl. (prosa@prosa.it)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "barcode.h"
#define SHRINK_AMOUNT 0.15 /* shrink the bars to account for ink spreading */
/*
* How do the "partial" and "textinfo" strings work?
*
* The first char in "partial" tells how much extra space to add to the
* left of the bars. For EAN-13, it is used to leave space to print the
* first digit, other codes may have '0' for no-extra-space-needed.
*
* The next characters are alternating bars and spaces, as multiples
* of the base dimension which is 1 unless the code is
* rescaled. Rescaling is calculated as the ratio from the requested
* width and the calculated width. Digits represent bar/space
* dimensions. Lower-case letters represent those bars that should
* extend lower than the others: 'a' is equivalent to '1', 'b' is '2' and
* so on.
*
* The "textinfo" string is made up of fields "%lf:%lf:%c" separated by
* blank space. The first integer is the x position of the character,
* the second is the font size (before rescaling) and the char item is
* the charcter to be printed.
*
* Both the "partial" and "textinfo" strings may include "-" or "+" as
* special characters (in "textinfo" the char should be a standalone
* word). They state where the text should be printed: below the bars
* ("-", default) or above the bars. This is used, for example, to
* print the add-5 and add-2 codes to the right of UPC or EAN codes
* (the add-5 extension is mostly used in ISBN codes.
*/
int Barcode_ps_print(struct Barcode_Item *bc, FILE *f)
{
int i, j, k, barlen, printable=1;
double f1, f2, fsav=0;
int mode = '-'; /* text below bars */
double scalef=1, xpos, x0, y0, yr;
unsigned char *ptr;
unsigned char c;
if (!bc->partial || !bc->textinfo) {
bc->error = EINVAL;
return -1;
}
/*
* Maybe this first part can be made common to several printing back-ends,
* we'll see how that works when other ouput engines are added
*/
/* First, calculate barlen */
barlen = bc->partial[0] - '0';
for (ptr = bc->partial+1; *ptr; ptr++)
if (isdigit(*ptr))
barlen += (*ptr - '0');
else if (islower(*ptr))
barlen += (*ptr - 'a'+1);
/* The scale factor depends on bar length */
if (!bc->scalef) {
if (!bc->width) bc->width = barlen; /* default */
scalef = bc->scalef = (double)bc->width / (double)barlen;
}
/* The width defaults to "just enough" */
if (!bc->width) bc->width = barlen * scalef +1;
/* But it can be too small, in this case enlarge and center the area */
if (bc->width < barlen * scalef) {
int wid = barlen * scalef + 1;
bc->xoff -= (wid - bc->width)/2 ;
bc->width = wid;
/* Can't extend too far on the left */
if (bc->xoff < 0) {
bc->width += -bc->xoff;
bc->xoff = 0;
}
}
/* The height defaults to 80 points (rescaled) */
if (!bc->height) bc->height = 80 * scalef;
#if 0
/* If too small (5 + text), enlarge and center */
i = 5 + 10 * ((bc->flags & BARCODE_NO_ASCII)==0);
if (bc->height < i * scalef ) {
int hei = i * scalef;
bc->yoff -= (hei-bc->height)/2;
bc->height = hei;
if (bc->yoff < 0) {
bc->height += -bc->yoff;
bc->yoff = 0;
}
}
#else
/* If too small (5 + text), reduce the scale factor and center */
i = 5 + 10 * ((bc->flags & BARCODE_NO_ASCII)==0);
if (bc->height < i * scalef ) {
double scaleg = ((double)bc->height) / i;
int wid = bc->width * scaleg / scalef;
bc->xoff += (bc->width - wid)/2;
bc->width = wid;
scalef = scaleg;
}
#endif
/*
* Ok, then deal with actual ps (eps) output
*/
if (!(bc->flags & BARCODE_OUT_NOHEADERS)) { /* spit a header first */
if (bc->flags & BARCODE_OUT_EPS)
fprintf(f, "%%!PS-Adobe-2.0 EPSF-1.2\n");
else
fprintf(f, "%%!PS-Adobe-2.0\n");
fprintf(f, "%%%%Creator: libbarcode\n");
if (bc->flags & BARCODE_OUT_EPS) {
fprintf(f, "%%%%BoundingBox: %i %i %i %i\n",
bc->xoff,
bc->yoff,
bc->xoff + bc->width + 2* bc->margin,
bc->yoff + bc->height + 2* bc->margin);
}
fprintf(f, "%%%%EndComments\n");
if (bc->flags & BARCODE_OUT_PS) {
fprintf(f, "%%%%EndProlog\n\n");
fprintf(f, "%%%%Page: 1 1\n\n");
}
}
/* Print some informative comments */
for (i=0; bc->ascii[i]; i++)
if (bc->ascii[i] < ' ')
printable = 0;
fprintf(f,"%% Printing barcode for \"%s\", scaled %5.2f",
printable ? bc->ascii : "<unprintable string>", scalef);
if (bc->encoding)
fprintf(f,", encoded using \"%s\"",bc->encoding);
fprintf(f, "\n");
fprintf(f,"%% The space/bar succession is represented "
"by the following widths (space first):\n"
"%% ");
for (i=0; i<strlen(bc->partial); i++) {
unsigned char c = bc->partial[i];
if (isdigit(c)) putc(c, f);
if (islower(c)) putc(c-'a'+'1', f);
if (isupper(c)) putc(c-'A'+'1', f);
}
/* open array for "forall" */
fprintf(f, "\n[\n%% height xpos ypos width"
" height xpos ypos width\n");
xpos = bc->margin + (bc->partial[0]-'0') * scalef;
for (ptr = bc->partial+1, i=1; *ptr; ptr++, i++) {
/* special cases: '+' and '-' */
if (*ptr == '+' || *ptr == '-') {
mode = *ptr; /* don't count it */ i++; continue;
}
/* j is the width of this bar/space */
if (isdigit (*ptr)) j = *ptr-'0';
else j = *ptr-'a'+1;
if (i%2) { /* bar */
x0 = bc->xoff + xpos + (j*scalef)/2;
y0 = bc->yoff + bc->margin;
yr = bc->height;
if (!(bc->flags & BARCODE_NO_ASCII)) { /* leave space for text */
if (mode == '-') {
/* text below bars: 10 points or five points */
y0 += (isdigit(*ptr) ? 10 : 5) * scalef;
yr -= (isdigit(*ptr) ? 10 : 5) * scalef;
} else { /* '+' */
/* text above bars: 10 or 0 from bottom, and 10 from top */
y0 += (isdigit(*ptr) ? 10 : 0) * scalef;
yr -= (isdigit(*ptr) ? 20 : 10) * scalef;
}
}
/* Define an array and then use "forall" (Hans Schou) */
fprintf(f," [%5.2f %6.2f %6.2f %5.2f]%s",
yr, x0, y0, (j * scalef) - SHRINK_AMOUNT,
i%4 == 1 ? " " : "\n");
}
xpos += j * scalef;
}
fprintf(f,"\n]\t{ {} forall setlinewidth moveto 0 exch rlineto stroke} "
"bind forall\n");
/* Then, the text */
mode = '-'; /* reinstantiate default */
if (!(bc->flags & BARCODE_NO_ASCII)) {
fprintf(f, "[\n%% char xpos ypos fontsize\n");
k=0; /* k is the "previous font size" */
for (ptr = bc->textinfo; ptr; ptr = strchr(ptr, ' ')) {
while (*ptr == ' ') ptr++;
if (!*ptr) break;
if (*ptr == '+' || *ptr == '-') {
mode = *ptr; continue;
}
if (sscanf(ptr, "%lf:%lf:%c", &f1, &f2, &c) != 3) {
fprintf(stderr, "barcode: impossible data: %s\n", ptr);
continue;
}
fprintf(f, " [(");
/* Both the backslash and the two parens are special */
if (c=='\\' || c==')' || c=='(')
fprintf(f, "\\%c) ", c);
else
fprintf(f, "%c) ", c);
fprintf(f, "%6.2f %6.2f %5.2f]\n",
bc->xoff + f1 * scalef + bc->margin,
mode == '-'
? (double)bc->yoff + bc->margin
: (double)bc->yoff + bc->margin+bc->height - 8*scalef,
fsav == f2 ? 0.0 : f2 * scalef);
fsav = f2;
}
fprintf(f,"] { {} forall dup 0.00 ne {\n\t"
"/Helvetica findfont exch scalefont setfont\n"
" } {pop} ifelse\n"
" moveto show} bind forall\n");
}
fprintf(f,"%% End barcode for \"%s\"\n\n",
printable ? bc->ascii : "<unprintable string>");
if (!(bc->flags & BARCODE_OUT_NOHEADERS)) {
if (bc->flags & BARCODE_OUT_PS) {
fprintf(f,"showpage\n");
fprintf(f, "%%%%Trailer\n\n");
}
}
return 0;
}
+178
View File
@@ -0,0 +1,178 @@
#include "QBarCode.h"
#include "ui_myBarCode.h"
#include "QImage"
#include "QFile"
#include "QFileInfo"
#include "QDebug"
#include "stdio.h"
QBarCode::QBarCode(QWidget *parent) :
QDialog(parent),
ui(new Ui::QBarCode)
{
ui->setupUi(this);
connect(ui->BarCodeGenerate,SIGNAL(pressed()),this,SLOT(onEnCodeBar()));
ui->lineEdit->setText("12345678ABCDEFG");
//onEnCodeBar();
}
QBarCode::~QBarCode()
{
delete ui;
}
void QBarCode::onEnCodeBar(){
QFile f1;
//ui->lineEdit->setText("dfdsfdsfdsfdsf");
int ps = 1, pcl = 0, oflags;
ps = 0; pcl = 0;
oflags = BARCODE_OUT_PS | BARCODE_OUT_NOHEADERS;
// char *txt = ui->lineEdit->text.toStdString().c_str();
//sprintf(txt,"%s", (char *)ui->lineEdit->text().data());
/* and my data as code-128B autodetected */
QString txt =ui->lineEdit->text();
Barcode_Encode_and_Print((char *)txt.toStdString().c_str(),stdout, 0, 60, 240, 510,
oflags);
/* A few code-39 ones */
// Barcode_Encode_and_Print("silly code",stdout, 0, 0, 40, 320,
// BARCODE_39 | oflags);
// Barcode_Encode_and_Print("SAMPLE CODES",stdout, 100, 30, 400, 80,
// BARCODE_39 | oflags);
/* ISBN with add-5 */
// Barcode_Encode_and_Print("1-56592-292-1 90000",stdout, 0, 0, 40, 430,
// BARCODE_ISBN | oflags);
}
/*
* Do it all in one step
*/
int QBarCode::Barcode_Encode_and_Print(char *text, FILE *f, int wid, int hei,
int xoff, int yoff, int flags)
{
struct Barcode_Item * bc;
if (!(bc=Barcode_Create(text))) {
qDebug()<<"mem less then:";//<< -ENOMEM ;
return -1;
}
if ( Barcode_Position(bc, wid, hei, xoff, yoff, 0.0) < 0
|| Barcode_Encode(bc, flags) < 0
//|| Barcode_Print(bc, f, flags) < 0
) {
qDebug()<< bc->error;
Barcode_Delete(bc);
return -1;
}
//QFile f1;
bcText = text;
bcTextinfo = bc->textinfo;
bcPartial = bc->partial;
ui->textEdit->setText(bcPartial);
Barcode_ToImage(bc);
Barcode_Delete(bc);
return 0;
}
// 将条形码编码转换成点阵图形
int QBarCode::Barcode_ToImage(Barcode_Item * bc ){
bc->ascii;
bc->partial;
bc->textinfo;
int len =QString(bc->partial).length();
bcWidth =6;
for(int i=0;i<len;i++)
bcWidth+= (bc->partial[i]&0x0f);
//
//bcWidth = len;
bcHeight = 40;
QImage image(bcWidth,bcHeight,QImage::Format_ARGB32);
//image.dotsPerMeterX()
//image.size().setHeight(50);
image.fill(0x00ffffff);
//QPainter painter(&image);
//ui->textEdit->document()->drawContents (&painter, image.rect()); /*将text写到pic*/
QString txt = bc->ascii;
ui->textEdit->setText( QString().sprintf("W:%d,H:%d,Len:%d",ui->BarCodeView->width(),ui->BarCodeView->height(),len));
//0b1a2a4123221223211221132221231213212223112312131311222314111b3c1a1b
//11:12:1 22:12:2 33:12:3 44:12:4 55:12:5 66:12:6 77:12:7 88:12:8
//02112141232212232112211322212312132122231123121313112223141112331112
memset(pointMap,0,sizeof(pointMap));
unsigned char *img= image.bits();
for(int j=0;j< 20;j++){
int i=3;
unsigned char p=0;
for(int n=0;( n<len);n++)
{
int c= bc->partial[n];
if(c<0x30 || c>127) continue;
c = c-0x30;
if(n%2==1){
for(int r=0;r<c;r++){
*( img+j*bcWidth*4+i*4)= 0;
*( img+j*bcWidth*4+i*4+1)= 0;
*( img+j*bcWidth*4+i*4+2)= 0;
*( img+j*bcWidth*4+i*4+3)= 0;
i++;
// p= (p<<1) | 0x01;
// pointMap[j*bcWidth+i]=1;
}
}
else i+=c;
}
}
QString fileName="\\home\\plg\\doc\\"+ txt + ".BMP" ;
image.save(fileName);
QFileInfo(fileName).fileName();
// ui->labBarCode->setPixmap(QPixmap(QString::fromUtf8(".\\imgd.BMP")));
//ui->widgetPrintTextDisplay->dat = pointMap;
ShowBarCode(fileName);
}
void QBarCode::ShowBarCode(QString fileName)
{
/****************界面初始化********************************/
this->pictureName =fileName ;
scene = new QGraphicsScene;
scene->setSceneRect( -200,0,bcWidth*4+200,bcHeight);
scene->setItemIndexMethod(QGraphicsScene::NoIndex);
QPixmap pixmap(this->pictureName);
pixmap = pixmap.scaledToWidth(2.5*bcWidth);
item = scene->addPixmap(pixmap);
/***************设置view的场景*****************************/
ui->BarCodeView->setScene(scene);
ui->BarCodeView->setRenderHint(QPainter::Antialiasing);
ui->BarCodeView->setCacheMode(QGraphicsView::CacheBackground);
ui->BarCodeView->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
ui->BarCodeView->setDragMode(QGraphicsView::ScrollHandDrag);
//ui->graphicsView->resize(400,300);
ui->BarCodeView->setScene(scene);//设置view的场景
}
+44
View File
@@ -0,0 +1,44 @@
#ifndef QBARCODE_H
#define QBARCODE_H
#include <QDialog>
#include "barcode.h"
#include "QGraphicsScene"
#include "QGraphicsPixmapItem"
namespace Ui {
class QBarCode;
}
class QBarCode : public QDialog
{
Q_OBJECT
public:
explicit QBarCode(QWidget *parent = 0);
~QBarCode();
unsigned char pointMap[40*1000];
QString pictureName;//当前显示的图片
private slots:
void onEnCodeBar();
private:
void ShowBarCode(QString fileName);
int Barcode_Encode_and_Print(char *text, FILE *f, int wid, int hei,
int xoff, int yoff, int flags);
int Barcode_ToImage(Barcode_Item * bc );
QGraphicsScene *scene;//声明scene
QGraphicsPixmapItem *item;//声明item
QString bcPartial;
QString bcTextinfo;
QString bcText;
int bcWidth,bcHeight;
private:
Ui::QBarCode *ui;
};
#endif // QBARCODE_H
+147
View File
@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QBarCode</class>
<widget class="QWidget" name="QBarCode">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>680</width>
<height>316</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="7">
<widget class="QGraphicsView" name="BarCodeView"/>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>条形码类型</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>字体</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLabel" name="label_3">
<property name="text">
<string>条形码高度</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QLabel" name="label_4">
<property name="text">
<string>放大等级</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QComboBox" name="BarCodeType"/>
</item>
<item row="3" column="2">
<widget class="QComboBox" name="BarCodeFont">
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QComboBox" name="BarCodeHeigh"/>
</item>
<item row="3" column="4">
<widget class="QSpinBox" name="BarCodeScale">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>10</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="3" column="6">
<widget class="QPushButton" name="BarCodeInsert">
<property name="text">
<string>插入文档</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>文本信息</string>
</property>
</widget>
</item>
<item row="4" column="1" colspan="4">
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item row="1" column="0" colspan="7">
<widget class="QTextEdit" name="textEdit">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>60</height>
</size>
</property>
</widget>
</item>
<item row="2" column="5" colspan="2">
<widget class="QLabel" name="labFileName">
<property name="text">
<string>FileName</string>
</property>
</widget>
</item>
<item row="3" column="5">
<widget class="QPushButton" name="pushBtnOpenFile">
<property name="text">
<string>打开文件</string>
</property>
</widget>
</item>
<item row="4" column="5">
<widget class="QPushButton" name="BarCodeGenerate">
<property name="text">
<string>生成条形码</string>
</property>
</widget>
</item>
<item row="4" column="6">
<widget class="QPushButton" name="pushBtnColse">
<property name="text">
<string>关闭</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labStatus">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>