提交原始齿轮泵代码
This commit is contained in:
@@ -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_ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* 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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* 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 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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的场景
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user