Initial transfer from CVS

Transfer of version 2.3.2 from CVS repository
This commit is contained in:
Robin Stuart 2010-06-10 21:52:50 +01:00
commit 511fadef30
152 changed files with 58999 additions and 0 deletions

363
backend/2of5.c Normal file
View file

@ -0,0 +1,363 @@
/* 2of5.c - Handles Code 2 of 5 barcodes */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#ifdef _MSC_VER
#include <malloc.h>
#endif
static char *C25MatrixTable[10] = {"113311", "311131", "131131", "331111", "113131", "313111",
"133111", "111331", "311311", "131311"};
static char *C25IndustTable[10] = {"1111313111", "3111111131", "1131111131", "3131111111", "1111311131",
"3111311111", "1131311111", "1111113131", "3111113111", "1131113111"};
static char *C25InterTable[10] = {"11331", "31113", "13113", "33111", "11313", "31311", "13311", "11133",
"31131", "13131"};
int matrix_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Code 2 of 5 Standard (Code 2 of 5 Matrix) */
int i, error_number;
char dest[512]; /* 6 + 80 * 6 + 6 + 1 ~ 512*/
error_number = 0;
if(length > 80) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
/* start character */
strcpy(dest, "411111");
for(i = 0; i < length; i++) {
lookup(NEON, C25MatrixTable, source[i], dest);
}
/* Stop character */
concat (dest, "41111");
expand(symbol, dest);
ustrcpy(symbol->text, source);
return error_number;
}
int industrial_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Code 2 of 5 Industrial */
int i, error_number;
char dest[512]; /* 6 + 40 * 10 + 6 + 1 */
error_number = 0;
if(length > 45) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid character in data");
return error_number;
}
/* start character */
strcpy(dest, "313111");
for(i = 0; i < length; i++) {
lookup(NEON, C25IndustTable, source[i], dest);
}
/* Stop character */
concat (dest, "31113");
expand(symbol, dest);
ustrcpy(symbol->text, source);
return error_number;
}
int iata_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Code 2 of 5 IATA */
int i, error_number;
char dest[512]; /* 4 + 45 * 10 + 3 + 1 */
error_number = 0;
if(length > 45) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
/* start */
strcpy(dest, "1111");
for(i = 0; i < length; i++) {
lookup(NEON, C25IndustTable, source[i], dest);
}
/* stop */
concat (dest, "311");
expand(symbol, dest);
ustrcpy(symbol->text, source);
return error_number;
}
int logic_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Code 2 of 5 Data Logic */
int i, error_number;
char dest[512]; /* 4 + 80 * 6 + 3 + 1 */
error_number = 0;
if(length > 80) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
/* start character */
strcpy(dest, "1111");
for(i = 0; i < length; i++) {
lookup(NEON, C25MatrixTable, source[i], dest);
}
/* Stop character */
concat (dest, "311");
expand(symbol, dest);
ustrcpy(symbol->text, source);
return error_number;
}
int interleaved_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Code 2 of 5 Interleaved */
int i, j, k, error_number;
char bars[7], spaces[7], mixed[14], dest[1000];
#ifndef _MSC_VER
unsigned char temp[length + 2];
#else
unsigned char* temp = (unsigned char *)_alloca((length + 2) * sizeof(unsigned char));
#endif
error_number = 0;
if(length > 89) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if (error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
ustrcpy(temp, (unsigned char *) "");
/* Input must be an even number of characters for Interlaced 2 of 5 to work:
if an odd number of characters has been entered then add a leading zero */
if ((length % 2) != 0)
{
ustrcpy(temp, (unsigned char *) "0");
length++;
}
uconcat(temp, source);
/* start character */
strcpy(dest, "1111");
for(i = 0; i < length; i+=2 )
{
/* look up the bars and the spaces and put them in two strings */
strcpy(bars, "");
lookup(NEON, C25InterTable, temp[i], bars);
strcpy(spaces, "");
lookup(NEON, C25InterTable, temp[i + 1], spaces);
/* then merge (interlace) the strings together */
k = 0;
for(j = 0; j <= 4; j++)
{
mixed[k] = bars[j]; k++;
mixed[k] = spaces[j]; k++;
}
mixed[k] = '\0';
concat (dest, mixed);
}
/* Stop character */
concat (dest, "311");
expand(symbol, dest);
ustrcpy(symbol->text, temp);
return error_number;
}
int itf14(struct zint_symbol *symbol, unsigned char source[], int length)
{
int i, error_number, zeroes;
unsigned int count, check_digit;
char localstr[16];
error_number = 0;
count = 0;
if(length > 13) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid character in data");
return error_number;
}
/* Add leading zeros as required */
zeroes = 13 - length;
for(i = 0; i < zeroes; i++) {
localstr[i] = '0';
}
strcpy(localstr + zeroes, (char *)source);
/* Calculate the check digit - the same method used for EAN-13 */
for (i = 12; i >= 0; i--)
{
count += ctoi(localstr[i]);
if ((i%2) == 0)
{
count += 2 * ctoi(localstr[i]);
}
}
check_digit = 10 - (count%10);
if (check_digit == 10) { check_digit = 0; }
localstr[13] = itoc(check_digit);
localstr[14] = '\0';
error_number = interleaved_two_of_five(symbol, (unsigned char *)localstr, strlen(localstr));
ustrcpy(symbol->text, (unsigned char*)localstr);
return error_number;
}
int dpleit(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Deutshe Post Leitcode */
int i, error_number;
unsigned int count, check_digit;
char localstr[16];
int zeroes;
error_number = 0;
count = 0;
if(length > 13) {
strcpy(symbol->errtxt, "Input wrong length");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
zeroes = 13 - length;
for(i = 0; i < zeroes; i++)
localstr[i] = '0';
strcpy(localstr + zeroes, (char *)source);
for (i = 12; i >= 0; i--)
{
count += 4 * ctoi(localstr[i]);
if (!((i%2) == 0))
{
count += 5 * ctoi(localstr[i]);
}
}
check_digit = 10 - (count%10);
if (check_digit == 10) { check_digit = 0; }
localstr[13] = itoc(check_digit);
localstr[14] = '\0';
error_number = interleaved_two_of_five(symbol, (unsigned char *)localstr, strlen(localstr));
ustrcpy(symbol->text, (unsigned char*)localstr);
return error_number;
}
int dpident(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Deutsche Post Identcode */
int i, error_number, zeroes;
unsigned int count, check_digit;
char localstr[16];
count = 0;
if(length > 11) {
strcpy(symbol->errtxt, "Input wrong length");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
zeroes = 11 - length;
for(i = 0; i < zeroes; i++)
localstr[i] = '0';
strcpy(localstr + zeroes, (char *)source);
for (i = 10; i >= 0; i--)
{
count += 4 * ctoi(localstr[i]);
if (!((i%2) == 0))
{
count += 5 * ctoi(localstr[i]);
}
}
check_digit = 10 - (count%10);
if (check_digit == 10) { check_digit = 0; }
localstr[11] = itoc(check_digit);
localstr[12] = '\0';
error_number = interleaved_two_of_five(symbol, (unsigned char *)localstr, strlen(localstr));
ustrcpy(symbol->text, (unsigned char*)localstr);
return error_number;
}

27
backend/CMakeLists.txt Normal file
View file

@ -0,0 +1,27 @@
# (c) 2008 by BogDan Vatra < bogdan@licentia.eu >
project(zint)
find_package(PNG)
set(zint_COMMON_SRCS common.c library.c ps.c large.c reedsol.c gs1.c svg.c png.c)
set(zint_ONEDIM_SRCS code.c code128.c 2of5.c upcean.c telepen.c medical.c plessey.c rss.c)
set(zint_POSTAL_SRCS postal.c auspost.c imail.c)
set(zint_TWODIM_SRCS code16k.c dmatrix.c dm200.c pdf417.c qr.c maxicode.c composite.c aztec.c code49.c code1.c gridmtx.c)
set(zint_SRCS ${zint_COMMON_SRCS} ${zint_ONEDIM_SRCS} ${zint_POSTAL_SRCS} ${zint_TWODIM_SRCS} )
if(PNG_FOUND)
include_directories( ${PNG_INCLUDES} )
else(PNG_FOUND)
add_definitions (-DNO_PNG)
endif(PNG_FOUND)
add_library(zint SHARED ${zint_SRCS})
set_target_properties(zint PROPERTIES SOVERSION "${ZINT_VERSION_MAJOR}.${ZINT_VERSION_MINOR}"
VERSION ${ZINT_VERSION})
target_link_libraries(zint ${PNG_LIBRARIES} )
install(TARGETS zint ${INSTALL_TARGETS_DEFAULT_ARGS} )
install(FILES zint.h DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel)

133
backend/DEVELOPER Normal file
View file

@ -0,0 +1,133 @@
Contents
--------
Here is a guide to which bit of source code does what.
2of5.c:
Matrix 2 of 5
Industrial 2 of 5
IATA 2 of 5
Data Logic
Interleaved 2 of 5
ITF-14
Deutche Post Leitcode
Deutche Post Identcode
auspost.c:
Australia Post Standard Customer Barcode
Australia Post Customer Barcode 2
Australia Post Customer Barcode 3
Australia Post Reply Paid Barcode
Australia Post Routing Barcode
Australia Post Redirect Barcode
aztec.c:
Aztec Code
Compact Aztec Code
Aztec Runes
blockf.c:
Codablock-F
code128.c:
Code 128
Code 128 Subset B
NVE-18
GS1-128 (UCC/EAN-128)
EAN-14
code16k.c:
Code 16k
code.c:
Code 11
Code 39
Pharmazentral Nummer (PZN)
Extended Code 39 (Code 39+)
Code 93
LOGMARS
Channel Code
code1.c:
Code One
code49.c:
Code 49
composite.c:
CC-A Composite Symbology
CC-B Composite Symbology
CC-C Composite Symbology
dm200.c:
Data Matrix ECC 200
dmatrix.c:
Data Matrix ECC 000
Data Matrix ECC 050
Data Matrix ECC 080
Data Matrix ECC 100
Data Matrix ECC 140
gridmtx.c:
Grid Matrix
imail.c:
USPS OneCode (Intelligent Mail)
maxicode.c:
UPS Maxicode
medical.c:
Pharma Code
Two Track Pharma Code
Codabar
Code 32
pdf417.c:
PDF417
Truncated PDF417
MicroPDF417
plessey.c:
UK Plessey Code (bidirectional)
MSI Plessey
postal.c:
PostNet
PLANET
Facing Identification Mark (FIM)
Royal Mail 4-State Country Code (RM4SCC)
KIX Code
DAFT Code
Flattermarken
Korean Postal Code
Japanese Postal Code
qr.c:
QR Code
Micro QR Code
rss.c:
GS1 DataBar (DataBar-14) (RSS-14)
GS1 DataBar Stacked (RSS-14 Stacked)
GS1 DataBar Stacked Omnidirectional (DataBar-14 Stacked Omnidirectional)
(RSS-14 Stacked Omnidirectional)
GS1 DataBar Limited (RSS Limited)
GS1 DataBar Expanded (RSS Expanded)
GS1 DataBar Expanded Stacked (RSS Expanded Stacked)
telepen.c:
Telepen ASCII
Telepen Numeric
upcean.c:
UPC-A
UPC-E
EAN-2 add-on
EAN-5 add-on
EAN-8
EAN-13
SBN (verification)
ISBN (verification)
ISBN-13 (verification)

54
backend/Makefile Normal file
View file

@ -0,0 +1,54 @@
# Linux makefile for libzint
#
# make compiles
# make install copies to /usr/local/lib
# make uninstall removes library
# make clean cleans up a previous compilation and any object or editor files
#
ZINT_VERSION:=-DZINT_VERSION=\"2.3.2\"
CC := gcc
INCLUDE := -I/usr/include
CFLAGS := -g
prefix := /usr
includedir := $(prefix)/include
libdir := $(prefix)/lib
DESTDIR :=
COMMON:= common.c png.c library.c ps.c large.c reedsol.c gs1.c svg.c
COMMON_OBJ:= common.o png.o library.o ps.o large.o reedsol.o gs1.o svg.o
ONEDIM:= code.c code128.c 2of5.c upcean.c telepen.c medical.c plessey.c rss.c
ONEDIM_OBJ:= code.o code128.o 2of5.o upcean.o telepen.o medical.o plessey.o rss.o
POSTAL:= postal.c auspost.c imail.c
POSTAL_OBJ:= postal.o auspost.o imail.o
TWODIM:= code16k.c dmatrix.c dm200.c pdf417.c qr.c maxicode.c composite.c aztec.c code49.c code1.c gridmtx.c
TWODIM_OBJ:= code16k.o dmatrix.o dm200.o pdf417.o qr.o maxicode.o composite.o aztec.o code49.o code1.o gridmtx.o
LIBS:= `libpng12-config --I_opts --L_opts --ldflags` -lz -lm
libzint: code.c code128.c 2of5.c upcean.c medical.c telepen.c plessey.c postal.c auspost.c imail.c code16k.c dmatrix.c dm200.c reedsol.c pdf417.c maxicode.c rss.c common.c png.c library.c ps.c qr.c large.c composite.c aztec.c gs1.c svg.c code49.c code1.c gridmtx.c
$(CC) -Wall -fPIC $(CFLAGS) $(ZINT_VERSION) -c $(ONEDIM)
$(CC) -Wall -fPIC $(CFLAGS) $(ZINT_VERSION) -c $(POSTAL)
$(CC) -Wall -fPIC $(CFLAGS) $(ZINT_VERSION) -c $(TWODIM)
$(CC) -Wall -fPIC $(CFLAGS) $(ZINT_VERSION) -c $(COMMON)
$(CC) $(CFLAGS) $(ZINT_VERSION) -shared -Wl,-soname,libzint.so -o libzint.so.2.3.2 $(INCLUDE) $(COMMON_OBJ) $(ONEDIM_OBJ) $(TWODIM_OBJ) $(POSTAL_OBJ) $(LIBS)
ln -s libzint.so.* libzint.so
.PHONY: install uninstall clean dist
install:
test "$(UID)" = "0" && ldconfig -n $(PWD) || true
install -d $(DESTDIR)$(libdir)
mv libzint.* $(DESTDIR)$(libdir)
install -D -p --mode=0644 zint.h $(DESTDIR)$(includedir)/zint.h
uninstall:
rm $(DESTDIR)$(libdir)/libzint.*
rm $(DESTDIR)$(includedir)/zint.h
clean:
rm -f libzint.* *.o *.a *~

79
backend/Makefile.mingw Normal file
View file

@ -0,0 +1,79 @@
# Linux makefile for libzint
#
# make compiles with QR Code support
# make install copies to /usr/lib
# make uninstall removes library
# make clean cleans up a previous compilation and any object or editor files
#
ZINT_VERSION:=-DZINT_VERSION=\"2.3.2\"
CC:= gcc
AR:= ar rc
RANLIB:= ranlib
INCLUDE:= -I/mingw/include
CFLAGS:= -D_WIN32 -O2 -fms-extensions -mms-bitfields -fno-exceptions -fomit-frame-pointer -Wall
prefix := /mingw
includedir := $(prefix)/include
libdir := $(prefix)/lib
bindir := $(prefix)/bin
DESTDIR :=
APP:=zint
DLL:=$(APP).dll
STATLIB:=lib$(APP).a
COMMON_OBJ:= common.o png.o library.o ps.o large.o reedsol.o gs1.o svg.o
ONEDIM_OBJ:= code.o code128.o 2of5.o upcean.o telepen.o medical.o plessey.o rss.o
POSTAL_OBJ:= postal.o auspost.o imail.o
TWODIM_OBJ:= code16k.o dmatrix.o dm200.o pdf417.o qr.o maxicode.o composite.o aztec.o code49.o code1.o gridmtx.o
LIB_OBJ:= $(COMMON_OBJ) $(ONEDIM_OBJ) $(TWODIM_OBJ) $(POSTAL_OBJ)
DLL_OBJ:= $(LIB_OBJ:.o=.lo) dllversion.lo
ifeq ($(NO_PNG),true)
DEFINES+= -DNO_PNG
else
DEFINES_DLL+= -DPNG_DLL -DZLIB_DLL
LIBS+= -lpng -lz
endif
LIBS+= -lm
all: $(DLL) $(STATLIB)
%.lo:%.c
@echo Compiling $< ...
$(CC) $(CFLAGS) $(DEFINES) $(DEFINES_DLL) -DDLL_EXPORT -DPIC $(ZINT_VERSION) -c -o $@ $<
%.o:%.c
@echo Compiling $< ...
$(CC) $(CFLAGS) $(DEFINES) $(ZINT_VERSION) -c -o $@ $<
$(DLL):$(DLL_OBJ)
@echo Linking $@...
o2dll.sh -o $@ $(DLL_OBJ) $(LIBS)
$(STATLIB): $(LIB_OBJ)
@echo Linking $@...
$(AR) $@ $(LIB_OBJ)
-@ ($(RANLIB) $@ || true) >/dev/null 2>&1
.PHONY: install uninstall clean dist
install:
cp -fp libzint.* $(DESTDIR)$(libdir)
cp -fp zint.h $(DESTDIR)$(includedir)/zint.h
cp -fp zint.dll $(DESTDIR)$(bindir)
uninstall:
rm $(DESTDIR)$(libdir)/libzint.*
rm $(DESTDIR)$(includedir)/zint.h
rm $(DESTDIR)$(bindir)/zint.dll
clean:
rm -f *.lib *.dll *.o *.a *~ *.res *.exe *.def *.lo *.bak

248
backend/auspost.c Normal file
View file

@ -0,0 +1,248 @@
/* auspost.c - Handles Australia Post 4-State Barcode */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define GDSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #"
static char *AusNTable[10] = {"00", "01", "02", "10", "11", "12", "20", "21", "22", "30"};
static char *AusCTable[64] = {"222", "300", "301", "302", "310", "311", "312", "320", "321", "322",
"000", "001", "002", "010", "011", "012", "020", "021", "022", "100", "101", "102", "110",
"111", "112", "120", "121", "122", "200", "201", "202", "210", "211", "212", "220", "221",
"023", "030", "031", "032", "033", "103", "113", "123", "130", "131", "132", "133", "203",
"213", "223", "230", "231", "232", "233", "303", "313", "323", "330", "331", "332", "333",
"003", "013"};
static char *AusBarTable[64] = {"000", "001", "002", "003", "010", "011", "012", "013", "020", "021",
"022", "023", "030", "031", "032", "033", "100", "101", "102", "103", "110", "111", "112",
"113", "120", "121", "122", "123", "130", "131", "132", "133", "200", "201", "202", "203",
"210", "211", "212", "213", "220", "221", "222", "223", "230", "231", "232", "233", "300",
"301", "302", "303", "310", "311", "312", "313", "320", "321", "322", "323", "330", "331",
"332", "333"};
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#include "reedsol.h"
void rs_error(char data_pattern[])
{
/* Adds Reed-Solomon error correction to auspost */
int reader, triple_writer;
char triple[31], inv_triple[31];
unsigned char result[5];
triple_writer = 0;
for(reader = 2; reader < strlen(data_pattern); reader+= 3)
{
triple[triple_writer] = 0;
switch(data_pattern[reader])
{
case '1': triple[triple_writer] += 16; break;
case '2': triple[triple_writer] += 32; break;
case '3': triple[triple_writer] += 48; break;
}
switch(data_pattern[reader + 1])
{
case '1': triple[triple_writer] += 4; break;
case '2': triple[triple_writer] += 8; break;
case '3': triple[triple_writer] += 12; break;
}
switch(data_pattern[reader + 2])
{
case '1': triple[triple_writer] += 1; break;
case '2': triple[triple_writer] += 2; break;
case '3': triple[triple_writer] += 3; break;
}
triple_writer++;
}
for(reader = 0; reader < triple_writer; reader++)
{
inv_triple[reader] = triple[(triple_writer - 1) - reader];
}
rs_init_gf(0x43);
rs_init_code(4, 1);
rs_encode(triple_writer, (unsigned char*) inv_triple, result);
for(reader = 4; reader > 0; reader--)
{
concat(data_pattern, AusBarTable[(int)result[reader - 1]]);
}
rs_free();
}
int australia_post(struct zint_symbol *symbol, unsigned char source[], int length)
{
/* Handles Australia Posts's 4 State Codes */
/* Customer Standard Barcode, Barcode 2 or Barcode 3 system determined automatically
(i.e. the FCC doesn't need to be specified by the user) dependent
on the length of the input string */
/* The contents of data_pattern conform to the following standard:
0 = Tracker, Ascender and Descender
1 = Tracker and Ascender
2 = Tracker and Descender
3 = Tracker only */
int error_number, zeroes;
int writer;
unsigned int loopey, reader, h;
char data_pattern[200];
char fcc[3], dpid[10];
char localstr[30];
error_number = 0;
strcpy(localstr, "");
/* Do all of the length checking first to avoid stack smashing */
if(symbol->symbology == BARCODE_AUSPOST) {
/* Format control code (FCC) */
switch(length)
{
case 8: strcpy(fcc, "11"); break;
case 13: strcpy(fcc, "59"); break;
case 16: strcpy(fcc, "59"); error_number = is_sane(NEON, source, length); break;
case 18: strcpy(fcc, "62"); break;
case 23: strcpy(fcc, "62"); error_number = is_sane(NEON, source, length); break;
default: strcpy(symbol->errtxt, "Auspost input is wrong length");
return ERROR_TOO_LONG;
break;
}
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
} else {
if(length > 8) {
strcpy(symbol->errtxt, "Auspost input is too long");
return ERROR_TOO_LONG;
}
switch(symbol->symbology) {
case BARCODE_AUSREPLY: strcpy(fcc, "45"); break;
case BARCODE_AUSROUTE: strcpy(fcc, "87"); break;
case BARCODE_AUSREDIRECT: strcpy(fcc, "92"); break;
}
/* Add leading zeros as required */
zeroes = 8 - length;
memset(localstr, '0', zeroes);
localstr[8] = '\0';
}
concat(localstr, (char*)source);
h = strlen(localstr);
error_number = is_sane(GDSET, (unsigned char *)localstr, h);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
/* Verifiy that the first 8 characters are numbers */
memcpy(dpid, localstr, 8);
dpid[8] = '\0';
error_number = is_sane(NEON, (unsigned char *)dpid, strlen(dpid));
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in DPID");
return error_number;
}
/* Start character */
strcpy(data_pattern, "13");
/* Encode the FCC */
for(reader = 0; reader < 2; reader++)
{
lookup(NEON, AusNTable, fcc[reader], data_pattern);
}
/* printf("AUSPOST FCC: %s ", fcc); */
/* Delivery Point Identifier (DPID) */
for(reader = 0; reader < 8; reader++)
{
lookup(NEON, AusNTable, dpid[reader], data_pattern);
}
/* Customer Information */
if(h > 8)
{
if((h == 13) || (h == 18)) {
for(reader = 8; reader < h; reader++) {
lookup(GDSET, AusCTable, localstr[reader], data_pattern);
}
}
if((h == 16) || (h == 23)) {
for(reader = 8; reader < h; reader++) {
lookup(NEON, AusNTable, localstr[reader], data_pattern);
}
}
}
/* Filler bar */
h = strlen(data_pattern);
if(h == 22) {
concat(data_pattern, "3");
}
else if(h == 37) {
concat(data_pattern, "3");
}
else if(h == 52) {
concat(data_pattern, "3");
}
/* Reed Solomon error correction */
rs_error(data_pattern);
/* Stop character */
concat(data_pattern, "13");
/* Turn the symbol into a bar pattern ready for plotting */
writer = 0;
h = strlen(data_pattern);
for(loopey = 0; loopey < h; loopey++)
{
if((data_pattern[loopey] == '1') || (data_pattern[loopey] == '0'))
{
set_module(symbol, 0, writer);
}
set_module(symbol, 1, writer);
if((data_pattern[loopey] == '2') || (data_pattern[loopey] == '0'))
{
set_module(symbol, 2, writer);
}
writer += 2;
}
symbol->row_height[0] = 4;
symbol->row_height[1] = 2;
symbol->row_height[2] = 4;
symbol->rows = 3;
symbol->width = writer - 1;
return error_number;
}

1350
backend/aztec.c Normal file

File diff suppressed because it is too large Load diff

291
backend/aztec.h Normal file
View file

@ -0,0 +1,291 @@
/* aztec.c - Handles Aztec Mesa 2D Symbols */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define UPPER 1
#define LOWER 2
#define MIXED 4
#define PUNC 8
#define DIGIT 16
#define BINARY 32
static int AztecMap[] = { /* 151 x 151 data grid */
19969,19968,18851,18853,18855,18857,18859,18861,18863,18865,18867,0,18869,18871,18873,18875,18877,18879,18881,18883,18885,18887,18889,18891,18893,18895,18897,0,18899,18901,18903,18905,18907,18909,18911,18913,18915,18917,18919,18921,18923,18925,18927,0,18929,18931,18933,18935,18937,18939,18941,18943,18945,18947,18949,18951,18953,18955,18957,0,18959,18961,18963,18965,18967,18969,18971,18973,18975,18977,18979,18981,18983,18985,18987,0,18989,18991,18993,18995,18997,18999,19001,19003,19005,19007,19009,19011,19013,19015,19017,0,19019,19021,19023,19025,19027,19029,19031,19033,19035,19037,19039,19041,19043,19045,19047,0,19049,19051,19053,19055,19057,19059,19061,19063,19065,19067,19069,19071,19073,19075,19077,0,19079,19081,19083,19085,19087,19089,19091,19093,19095,19097,19099,19101,19103,19105,19107,0,19109,19111,19113,19115,19117,19119,19121,19123,19125,19127,19129,
19967,19966,18850,18852,18854,18856,18858,18860,18862,18864,18866,1,18868,18870,18872,18874,18876,18878,18880,18882,18884,18886,18888,18890,18892,18894,18896,1,18898,18900,18902,18904,18906,18908,18910,18912,18914,18916,18918,18920,18922,18924,18926,1,18928,18930,18932,18934,18936,18938,18940,18942,18944,18946,18948,18950,18952,18954,18956,1,18958,18960,18962,18964,18966,18968,18970,18972,18974,18976,18978,18980,18982,18984,18986,1,18988,18990,18992,18994,18996,18998,19000,19002,19004,19006,19008,19010,19012,19014,19016,1,19018,19020,19022,19024,19026,19028,19030,19032,19034,19036,19038,19040,19042,19044,19046,1,19048,19050,19052,19054,19056,19058,19060,19062,19064,19066,19068,19070,19072,19074,19076,1,19078,19080,19082,19084,19086,19088,19090,19092,19094,19096,19098,19100,19102,19104,19106,1,19108,19110,19112,19114,19116,19118,19120,19122,19124,19126,19128,
19965,19964,18849,18848,17763,17765,17767,17769,17771,17773,17775,0,17777,17779,17781,17783,17785,17787,17789,17791,17793,17795,17797,17799,17801,17803,17805,0,17807,17809,17811,17813,17815,17817,17819,17821,17823,17825,17827,17829,17831,17833,17835,0,17837,17839,17841,17843,17845,17847,17849,17851,17853,17855,17857,17859,17861,17863,17865,0,17867,17869,17871,17873,17875,17877,17879,17881,17883,17885,17887,17889,17891,17893,17895,0,17897,17899,17901,17903,17905,17907,17909,17911,17913,17915,17917,17919,17921,17923,17925,0,17927,17929,17931,17933,17935,17937,17939,17941,17943,17945,17947,17949,17951,17953,17955,0,17957,17959,17961,17963,17965,17967,17969,17971,17973,17975,17977,17979,17981,17983,17985,0,17987,17989,17991,17993,17995,17997,17999,18001,18003,18005,18007,18009,18011,18013,18015,0,18017,18019,18021,18023,18025,18027,18029,18031,18033,19130,19131,
19963,19962,18847,18846,17762,17764,17766,17768,17770,17772,17774,1,17776,17778,17780,17782,17784,17786,17788,17790,17792,17794,17796,17798,17800,17802,17804,1,17806,17808,17810,17812,17814,17816,17818,17820,17822,17824,17826,17828,17830,17832,17834,1,17836,17838,17840,17842,17844,17846,17848,17850,17852,17854,17856,17858,17860,17862,17864,1,17866,17868,17870,17872,17874,17876,17878,17880,17882,17884,17886,17888,17890,17892,17894,1,17896,17898,17900,17902,17904,17906,17908,17910,17912,17914,17916,17918,17920,17922,17924,1,17926,17928,17930,17932,17934,17936,17938,17940,17942,17944,17946,17948,17950,17952,17954,1,17956,17958,17960,17962,17964,17966,17968,17970,17972,17974,17976,17978,17980,17982,17984,1,17986,17988,17990,17992,17994,17996,17998,18000,18002,18004,18006,18008,18010,18012,18014,1,18016,18018,18020,18022,18024,18026,18028,18030,18032,19132,19133,
19961,19960,18845,18844,17761,17760,16707,16709,16711,16713,16715,0,16717,16719,16721,16723,16725,16727,16729,16731,16733,16735,16737,16739,16741,16743,16745,0,16747,16749,16751,16753,16755,16757,16759,16761,16763,16765,16767,16769,16771,16773,16775,0,16777,16779,16781,16783,16785,16787,16789,16791,16793,16795,16797,16799,16801,16803,16805,0,16807,16809,16811,16813,16815,16817,16819,16821,16823,16825,16827,16829,16831,16833,16835,0,16837,16839,16841,16843,16845,16847,16849,16851,16853,16855,16857,16859,16861,16863,16865,0,16867,16869,16871,16873,16875,16877,16879,16881,16883,16885,16887,16889,16891,16893,16895,0,16897,16899,16901,16903,16905,16907,16909,16911,16913,16915,16917,16919,16921,16923,16925,0,16927,16929,16931,16933,16935,16937,16939,16941,16943,16945,16947,16949,16951,16953,16955,0,16957,16959,16961,16963,16965,16967,16969,18034,18035,19134,19135,
19959,19958,18843,18842,17759,17758,16706,16708,16710,16712,16714,1,16716,16718,16720,16722,16724,16726,16728,16730,16732,16734,16736,16738,16740,16742,16744,1,16746,16748,16750,16752,16754,16756,16758,16760,16762,16764,16766,16768,16770,16772,16774,1,16776,16778,16780,16782,16784,16786,16788,16790,16792,16794,16796,16798,16800,16802,16804,1,16806,16808,16810,16812,16814,16816,16818,16820,16822,16824,16826,16828,16830,16832,16834,1,16836,16838,16840,16842,16844,16846,16848,16850,16852,16854,16856,16858,16860,16862,16864,1,16866,16868,16870,16872,16874,16876,16878,16880,16882,16884,16886,16888,16890,16892,16894,1,16896,16898,16900,16902,16904,16906,16908,16910,16912,16914,16916,16918,16920,16922,16924,1,16926,16928,16930,16932,16934,16936,16938,16940,16942,16944,16946,16948,16950,16952,16954,1,16956,16958,16960,16962,16964,16966,16968,18036,18037,19136,19137,
19957,19956,18841,18840,17757,17756,16705,16704,15683,15685,15687,0,15689,15691,15693,15695,15697,15699,15701,15703,15705,15707,15709,15711,15713,15715,15717,0,15719,15721,15723,15725,15727,15729,15731,15733,15735,15737,15739,15741,15743,15745,15747,0,15749,15751,15753,15755,15757,15759,15761,15763,15765,15767,15769,15771,15773,15775,15777,0,15779,15781,15783,15785,15787,15789,15791,15793,15795,15797,15799,15801,15803,15805,15807,0,15809,15811,15813,15815,15817,15819,15821,15823,15825,15827,15829,15831,15833,15835,15837,0,15839,15841,15843,15845,15847,15849,15851,15853,15855,15857,15859,15861,15863,15865,15867,0,15869,15871,15873,15875,15877,15879,15881,15883,15885,15887,15889,15891,15893,15895,15897,0,15899,15901,15903,15905,15907,15909,15911,15913,15915,15917,15919,15921,15923,15925,15927,0,15929,15931,15933,15935,15937,16970,16971,18038,18039,19138,19139,
19955,19954,18839,18838,17755,17754,16703,16702,15682,15684,15686,1,15688,15690,15692,15694,15696,15698,15700,15702,15704,15706,15708,15710,15712,15714,15716,1,15718,15720,15722,15724,15726,15728,15730,15732,15734,15736,15738,15740,15742,15744,15746,1,15748,15750,15752,15754,15756,15758,15760,15762,15764,15766,15768,15770,15772,15774,15776,1,15778,15780,15782,15784,15786,15788,15790,15792,15794,15796,15798,15800,15802,15804,15806,1,15808,15810,15812,15814,15816,15818,15820,15822,15824,15826,15828,15830,15832,15834,15836,1,15838,15840,15842,15844,15846,15848,15850,15852,15854,15856,15858,15860,15862,15864,15866,1,15868,15870,15872,15874,15876,15878,15880,15882,15884,15886,15888,15890,15892,15894,15896,1,15898,15900,15902,15904,15906,15908,15910,15912,15914,15916,15918,15920,15922,15924,15926,1,15928,15930,15932,15934,15936,16972,16973,18040,18041,19140,19141,
19953,19952,18837,18836,17753,17752,16701,16700,15681,15680,14691,0,14693,14695,14697,14699,14701,14703,14705,14707,14709,14711,14713,14715,14717,14719,14721,0,14723,14725,14727,14729,14731,14733,14735,14737,14739,14741,14743,14745,14747,14749,14751,0,14753,14755,14757,14759,14761,14763,14765,14767,14769,14771,14773,14775,14777,14779,14781,0,14783,14785,14787,14789,14791,14793,14795,14797,14799,14801,14803,14805,14807,14809,14811,0,14813,14815,14817,14819,14821,14823,14825,14827,14829,14831,14833,14835,14837,14839,14841,0,14843,14845,14847,14849,14851,14853,14855,14857,14859,14861,14863,14865,14867,14869,14871,0,14873,14875,14877,14879,14881,14883,14885,14887,14889,14891,14893,14895,14897,14899,14901,0,14903,14905,14907,14909,14911,14913,14915,14917,14919,14921,14923,14925,14927,14929,14931,0,14933,14935,14937,15938,15939,16974,16975,18042,18043,19142,19143,
19951,19950,18835,18834,17751,17750,16699,16698,15679,15678,14690,1,14692,14694,14696,14698,14700,14702,14704,14706,14708,14710,14712,14714,14716,14718,14720,1,14722,14724,14726,14728,14730,14732,14734,14736,14738,14740,14742,14744,14746,14748,14750,1,14752,14754,14756,14758,14760,14762,14764,14766,14768,14770,14772,14774,14776,14778,14780,1,14782,14784,14786,14788,14790,14792,14794,14796,14798,14800,14802,14804,14806,14808,14810,1,14812,14814,14816,14818,14820,14822,14824,14826,14828,14830,14832,14834,14836,14838,14840,1,14842,14844,14846,14848,14850,14852,14854,14856,14858,14860,14862,14864,14866,14868,14870,1,14872,14874,14876,14878,14880,14882,14884,14886,14888,14890,14892,14894,14896,14898,14900,1,14902,14904,14906,14908,14910,14912,14914,14916,14918,14920,14922,14924,14926,14928,14930,1,14932,14934,14936,15940,15941,16976,16977,18044,18045,19144,19145,
19949,19948,18833,18832,17749,17748,16697,16696,15677,15676,14689,0,14688,13731,13733,13735,13737,13739,13741,13743,13745,13747,13749,13751,13753,13755,13757,0,13759,13761,13763,13765,13767,13769,13771,13773,13775,13777,13779,13781,13783,13785,13787,0,13789,13791,13793,13795,13797,13799,13801,13803,13805,13807,13809,13811,13813,13815,13817,0,13819,13821,13823,13825,13827,13829,13831,13833,13835,13837,13839,13841,13843,13845,13847,0,13849,13851,13853,13855,13857,13859,13861,13863,13865,13867,13869,13871,13873,13875,13877,0,13879,13881,13883,13885,13887,13889,13891,13893,13895,13897,13899,13901,13903,13905,13907,0,13909,13911,13913,13915,13917,13919,13921,13923,13925,13927,13929,13931,13933,13935,13937,0,13939,13941,13943,13945,13947,13949,13951,13953,13955,13957,13959,13961,13963,13965,13967,0,13969,14938,14939,15942,15943,16978,16979,18046,18047,19146,19147,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,
19947,19946,18831,18830,17747,17746,16695,16694,15675,15674,14687,0,14686,13730,13732,13734,13736,13738,13740,13742,13744,13746,13748,13750,13752,13754,13756,0,13758,13760,13762,13764,13766,13768,13770,13772,13774,13776,13778,13780,13782,13784,13786,0,13788,13790,13792,13794,13796,13798,13800,13802,13804,13806,13808,13810,13812,13814,13816,0,13818,13820,13822,13824,13826,13828,13830,13832,13834,13836,13838,13840,13842,13844,13846,0,13848,13850,13852,13854,13856,13858,13860,13862,13864,13866,13868,13870,13872,13874,13876,0,13878,13880,13882,13884,13886,13888,13890,13892,13894,13896,13898,13900,13902,13904,13906,0,13908,13910,13912,13914,13916,13918,13920,13922,13924,13926,13928,13930,13932,13934,13936,0,13938,13940,13942,13944,13946,13948,13950,13952,13954,13956,13958,13960,13962,13964,13966,0,13968,14940,14941,15944,15945,16980,16981,18048,18049,19148,19149,
19945,19944,18829,18828,17745,17744,16693,16692,15673,15672,14685,1,14684,13729,13728,12803,12805,12807,12809,12811,12813,12815,12817,12819,12821,12823,12825,1,12827,12829,12831,12833,12835,12837,12839,12841,12843,12845,12847,12849,12851,12853,12855,1,12857,12859,12861,12863,12865,12867,12869,12871,12873,12875,12877,12879,12881,12883,12885,1,12887,12889,12891,12893,12895,12897,12899,12901,12903,12905,12907,12909,12911,12913,12915,1,12917,12919,12921,12923,12925,12927,12929,12931,12933,12935,12937,12939,12941,12943,12945,1,12947,12949,12951,12953,12955,12957,12959,12961,12963,12965,12967,12969,12971,12973,12975,1,12977,12979,12981,12983,12985,12987,12989,12991,12993,12995,12997,12999,13001,13003,13005,1,13007,13009,13011,13013,13015,13017,13019,13021,13023,13025,13027,13029,13031,13033,13970,1,13971,14942,14943,15946,15947,16982,16983,18050,18051,19150,19151,
19943,19942,18827,18826,17743,17742,16691,16690,15671,15670,14683,0,14682,13727,13726,12802,12804,12806,12808,12810,12812,12814,12816,12818,12820,12822,12824,0,12826,12828,12830,12832,12834,12836,12838,12840,12842,12844,12846,12848,12850,12852,12854,0,12856,12858,12860,12862,12864,12866,12868,12870,12872,12874,12876,12878,12880,12882,12884,0,12886,12888,12890,12892,12894,12896,12898,12900,12902,12904,12906,12908,12910,12912,12914,0,12916,12918,12920,12922,12924,12926,12928,12930,12932,12934,12936,12938,12940,12942,12944,0,12946,12948,12950,12952,12954,12956,12958,12960,12962,12964,12966,12968,12970,12972,12974,0,12976,12978,12980,12982,12984,12986,12988,12990,12992,12994,12996,12998,13000,13002,13004,0,13006,13008,13010,13012,13014,13016,13018,13020,13022,13024,13026,13028,13030,13032,13972,0,13973,14944,14945,15948,15949,16984,16985,18052,18053,19152,19153,
19941,19940,18825,18824,17741,17740,16689,16688,15669,15668,14681,1,14680,13725,13724,12801,12800,11907,11909,11911,11913,11915,11917,11919,11921,11923,11925,1,11927,11929,11931,11933,11935,11937,11939,11941,11943,11945,11947,11949,11951,11953,11955,1,11957,11959,11961,11963,11965,11967,11969,11971,11973,11975,11977,11979,11981,11983,11985,1,11987,11989,11991,11993,11995,11997,11999,12001,12003,12005,12007,12009,12011,12013,12015,1,12017,12019,12021,12023,12025,12027,12029,12031,12033,12035,12037,12039,12041,12043,12045,1,12047,12049,12051,12053,12055,12057,12059,12061,12063,12065,12067,12069,12071,12073,12075,1,12077,12079,12081,12083,12085,12087,12089,12091,12093,12095,12097,12099,12101,12103,12105,1,12107,12109,12111,12113,12115,12117,12119,12121,12123,12125,12127,12129,13034,13035,13974,1,13975,14946,14947,15950,15951,16986,16987,18054,18055,19154,19155,
19939,19938,18823,18822,17739,17738,16687,16686,15667,15666,14679,0,14678,13723,13722,12799,12798,11906,11908,11910,11912,11914,11916,11918,11920,11922,11924,0,11926,11928,11930,11932,11934,11936,11938,11940,11942,11944,11946,11948,11950,11952,11954,0,11956,11958,11960,11962,11964,11966,11968,11970,11972,11974,11976,11978,11980,11982,11984,0,11986,11988,11990,11992,11994,11996,11998,12000,12002,12004,12006,12008,12010,12012,12014,0,12016,12018,12020,12022,12024,12026,12028,12030,12032,12034,12036,12038,12040,12042,12044,0,12046,12048,12050,12052,12054,12056,12058,12060,12062,12064,12066,12068,12070,12072,12074,0,12076,12078,12080,12082,12084,12086,12088,12090,12092,12094,12096,12098,12100,12102,12104,0,12106,12108,12110,12112,12114,12116,12118,12120,12122,12124,12126,12128,13036,13037,13976,0,13977,14948,14949,15952,15953,16988,16989,18056,18057,19156,19157,
19937,19936,18821,18820,17737,17736,16685,16684,15665,15664,14677,1,14676,13721,13720,12797,12796,11905,11904,11043,11045,11047,11049,11051,11053,11055,11057,1,11059,11061,11063,11065,11067,11069,11071,11073,11075,11077,11079,11081,11083,11085,11087,1,11089,11091,11093,11095,11097,11099,11101,11103,11105,11107,11109,11111,11113,11115,11117,1,11119,11121,11123,11125,11127,11129,11131,11133,11135,11137,11139,11141,11143,11145,11147,1,11149,11151,11153,11155,11157,11159,11161,11163,11165,11167,11169,11171,11173,11175,11177,1,11179,11181,11183,11185,11187,11189,11191,11193,11195,11197,11199,11201,11203,11205,11207,1,11209,11211,11213,11215,11217,11219,11221,11223,11225,11227,11229,11231,11233,11235,11237,1,11239,11241,11243,11245,11247,11249,11251,11253,11255,11257,12130,12131,13038,13039,13978,1,13979,14950,14951,15954,15955,16990,16991,18058,18059,19158,19159,
19935,19934,18819,18818,17735,17734,16683,16682,15663,15662,14675,0,14674,13719,13718,12795,12794,11903,11902,11042,11044,11046,11048,11050,11052,11054,11056,0,11058,11060,11062,11064,11066,11068,11070,11072,11074,11076,11078,11080,11082,11084,11086,0,11088,11090,11092,11094,11096,11098,11100,11102,11104,11106,11108,11110,11112,11114,11116,0,11118,11120,11122,11124,11126,11128,11130,11132,11134,11136,11138,11140,11142,11144,11146,0,11148,11150,11152,11154,11156,11158,11160,11162,11164,11166,11168,11170,11172,11174,11176,0,11178,11180,11182,11184,11186,11188,11190,11192,11194,11196,11198,11200,11202,11204,11206,0,11208,11210,11212,11214,11216,11218,11220,11222,11224,11226,11228,11230,11232,11234,11236,0,11238,11240,11242,11244,11246,11248,11250,11252,11254,11256,12132,12133,13040,13041,13980,0,13981,14952,14953,15956,15957,16992,16993,18060,18061,19160,19161,
19933,19932,18817,18816,17733,17732,16681,16680,15661,15660,14673,1,14672,13717,13716,12793,12792,11901,11900,11041,11040,10211,10213,10215,10217,10219,10221,1,10223,10225,10227,10229,10231,10233,10235,10237,10239,10241,10243,10245,10247,10249,10251,1,10253,10255,10257,10259,10261,10263,10265,10267,10269,10271,10273,10275,10277,10279,10281,1,10283,10285,10287,10289,10291,10293,10295,10297,10299,10301,10303,10305,10307,10309,10311,1,10313,10315,10317,10319,10321,10323,10325,10327,10329,10331,10333,10335,10337,10339,10341,1,10343,10345,10347,10349,10351,10353,10355,10357,10359,10361,10363,10365,10367,10369,10371,1,10373,10375,10377,10379,10381,10383,10385,10387,10389,10391,10393,10395,10397,10399,10401,1,10403,10405,10407,10409,10411,10413,10415,10417,11258,11259,12134,12135,13042,13043,13982,1,13983,14954,14955,15958,15959,16994,16995,18062,18063,19162,19163,
19931,19930,18815,18814,17731,17730,16679,16678,15659,15658,14671,0,14670,13715,13714,12791,12790,11899,11898,11039,11038,10210,10212,10214,10216,10218,10220,0,10222,10224,10226,10228,10230,10232,10234,10236,10238,10240,10242,10244,10246,10248,10250,0,10252,10254,10256,10258,10260,10262,10264,10266,10268,10270,10272,10274,10276,10278,10280,0,10282,10284,10286,10288,10290,10292,10294,10296,10298,10300,10302,10304,10306,10308,10310,0,10312,10314,10316,10318,10320,10322,10324,10326,10328,10330,10332,10334,10336,10338,10340,0,10342,10344,10346,10348,10350,10352,10354,10356,10358,10360,10362,10364,10366,10368,10370,0,10372,10374,10376,10378,10380,10382,10384,10386,10388,10390,10392,10394,10396,10398,10400,0,10402,10404,10406,10408,10410,10412,10414,10416,11260,11261,12136,12137,13044,13045,13984,0,13985,14956,14957,15960,15961,16996,16997,18064,18065,19164,19165,
19929,19928,18813,18812,17729,17728,16677,16676,15657,15656,14669,1,14668,13713,13712,12789,12788,11897,11896,11037,11036,10209,10208,9411,9413,9415,9417,1,9419,9421,9423,9425,9427,9429,9431,9433,9435,9437,9439,9441,9443,9445,9447,1,9449,9451,9453,9455,9457,9459,9461,9463,9465,9467,9469,9471,9473,9475,9477,1,9479,9481,9483,9485,9487,9489,9491,9493,9495,9497,9499,9501,9503,9505,9507,1,9509,9511,9513,9515,9517,9519,9521,9523,9525,9527,9529,9531,9533,9535,9537,1,9539,9541,9543,9545,9547,9549,9551,9553,9555,9557,9559,9561,9563,9565,9567,1,9569,9571,9573,9575,9577,9579,9581,9583,9585,9587,9589,9591,9593,9595,9597,1,9599,9601,9603,9605,9607,9609,10418,10419,11262,11263,12138,12139,13046,13047,13986,1,13987,14958,14959,15962,15963,16998,16999,18066,18067,19166,19167,
19927,19926,18811,18810,17727,17726,16675,16674,15655,15654,14667,0,14666,13711,13710,12787,12786,11895,11894,11035,11034,10207,10206,9410,9412,9414,9416,0,9418,9420,9422,9424,9426,9428,9430,9432,9434,9436,9438,9440,9442,9444,9446,0,9448,9450,9452,9454,9456,9458,9460,9462,9464,9466,9468,9470,9472,9474,9476,0,9478,9480,9482,9484,9486,9488,9490,9492,9494,9496,9498,9500,9502,9504,9506,0,9508,9510,9512,9514,9516,9518,9520,9522,9524,9526,9528,9530,9532,9534,9536,0,9538,9540,9542,9544,9546,9548,9550,9552,9554,9556,9558,9560,9562,9564,9566,0,9568,9570,9572,9574,9576,9578,9580,9582,9584,9586,9588,9590,9592,9594,9596,0,9598,9600,9602,9604,9606,9608,10420,10421,11264,11265,12140,12141,13048,13049,13988,0,13989,14960,14961,15964,15965,17000,17001,18068,18069,19168,19169,
19925,19924,18809,18808,17725,17724,16673,16672,15653,15652,14665,1,14664,13709,13708,12785,12784,11893,11892,11033,11032,10205,10204,9409,9408,8643,8645,1,8647,8649,8651,8653,8655,8657,8659,8661,8663,8665,8667,8669,8671,8673,8675,1,8677,8679,8681,8683,8685,8687,8689,8691,8693,8695,8697,8699,8701,8703,8705,1,8707,8709,8711,8713,8715,8717,8719,8721,8723,8725,8727,8729,8731,8733,8735,1,8737,8739,8741,8743,8745,8747,8749,8751,8753,8755,8757,8759,8761,8763,8765,1,8767,8769,8771,8773,8775,8777,8779,8781,8783,8785,8787,8789,8791,8793,8795,1,8797,8799,8801,8803,8805,8807,8809,8811,8813,8815,8817,8819,8821,8823,8825,1,8827,8829,8831,8833,9610,9611,10422,10423,11266,11267,12142,12143,13050,13051,13990,1,13991,14962,14963,15966,15967,17002,17003,18070,18071,19170,19171,
19923,19922,18807,18806,17723,17722,16671,16670,15651,15650,14663,0,14662,13707,13706,12783,12782,11891,11890,11031,11030,10203,10202,9407,9406,8642,8644,0,8646,8648,8650,8652,8654,8656,8658,8660,8662,8664,8666,8668,8670,8672,8674,0,8676,8678,8680,8682,8684,8686,8688,8690,8692,8694,8696,8698,8700,8702,8704,0,8706,8708,8710,8712,8714,8716,8718,8720,8722,8724,8726,8728,8730,8732,8734,0,8736,8738,8740,8742,8744,8746,8748,8750,8752,8754,8756,8758,8760,8762,8764,0,8766,8768,8770,8772,8774,8776,8778,8780,8782,8784,8786,8788,8790,8792,8794,0,8796,8798,8800,8802,8804,8806,8808,8810,8812,8814,8816,8818,8820,8822,8824,0,8826,8828,8830,8832,9612,9613,10424,10425,11268,11269,12144,12145,13052,13053,13992,0,13993,14964,14965,15968,15969,17004,17005,18072,18073,19172,19173,
19921,19920,18805,18804,17721,17720,16669,16668,15649,15648,14661,1,14660,13705,13704,12781,12780,11889,11888,11029,11028,10201,10200,9405,9404,8641,8640,1,7907,7909,7911,7913,7915,7917,7919,7921,7923,7925,7927,7929,7931,7933,7935,1,7937,7939,7941,7943,7945,7947,7949,7951,7953,7955,7957,7959,7961,7963,7965,1,7967,7969,7971,7973,7975,7977,7979,7981,7983,7985,7987,7989,7991,7993,7995,1,7997,7999,8001,8003,8005,8007,8009,8011,8013,8015,8017,8019,8021,8023,8025,1,8027,8029,8031,8033,8035,8037,8039,8041,8043,8045,8047,8049,8051,8053,8055,1,8057,8059,8061,8063,8065,8067,8069,8071,8073,8075,8077,8079,8081,8083,8085,1,8087,8089,8834,8835,9614,9615,10426,10427,11270,11271,12146,12147,13054,13055,13994,1,13995,14966,14967,15970,15971,17006,17007,18074,18075,19174,19175,
19919,19918,18803,18802,17719,17718,16667,16666,15647,15646,14659,0,14658,13703,13702,12779,12778,11887,11886,11027,11026,10199,10198,9403,9402,8639,8638,0,7906,7908,7910,7912,7914,7916,7918,7920,7922,7924,7926,7928,7930,7932,7934,0,7936,7938,7940,7942,7944,7946,7948,7950,7952,7954,7956,7958,7960,7962,7964,0,7966,7968,7970,7972,7974,7976,7978,7980,7982,7984,7986,7988,7990,7992,7994,0,7996,7998,8000,8002,8004,8006,8008,8010,8012,8014,8016,8018,8020,8022,8024,0,8026,8028,8030,8032,8034,8036,8038,8040,8042,8044,8046,8048,8050,8052,8054,0,8056,8058,8060,8062,8064,8066,8068,8070,8072,8074,8076,8078,8080,8082,8084,0,8086,8088,8836,8837,9616,9617,10428,10429,11272,11273,12148,12149,13056,13057,13996,0,13997,14968,14969,15972,15973,17008,17009,18076,18077,19176,19177,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,
19917,19916,18801,18800,17717,17716,16665,16664,15645,15644,14657,0,14656,13701,13700,12777,12776,11885,11884,11025,11024,10197,10196,9401,9400,8637,8636,0,7905,7904,7203,7205,7207,7209,7211,7213,7215,7217,7219,7221,7223,7225,7227,0,7229,7231,7233,7235,7237,7239,7241,7243,7245,7247,7249,7251,7253,7255,7257,0,7259,7261,7263,7265,7267,7269,7271,7273,7275,7277,7279,7281,7283,7285,7287,0,7289,7291,7293,7295,7297,7299,7301,7303,7305,7307,7309,7311,7313,7315,7317,0,7319,7321,7323,7325,7327,7329,7331,7333,7335,7337,7339,7341,7343,7345,7347,0,7349,7351,7353,7355,7357,7359,7361,7363,7365,7367,7369,7371,7373,7375,7377,0,8090,8091,8838,8839,9618,9619,10430,10431,11274,11275,12150,12151,13058,13059,13998,0,13999,14970,14971,15974,15975,17010,17011,18078,18079,19178,19179,
19915,19914,18799,18798,17715,17714,16663,16662,15643,15642,14655,1,14654,13699,13698,12775,12774,11883,11882,11023,11022,10195,10194,9399,9398,8635,8634,1,7903,7902,7202,7204,7206,7208,7210,7212,7214,7216,7218,7220,7222,7224,7226,1,7228,7230,7232,7234,7236,7238,7240,7242,7244,7246,7248,7250,7252,7254,7256,1,7258,7260,7262,7264,7266,7268,7270,7272,7274,7276,7278,7280,7282,7284,7286,1,7288,7290,7292,7294,7296,7298,7300,7302,7304,7306,7308,7310,7312,7314,7316,1,7318,7320,7322,7324,7326,7328,7330,7332,7334,7336,7338,7340,7342,7344,7346,1,7348,7350,7352,7354,7356,7358,7360,7362,7364,7366,7368,7370,7372,7374,7376,1,8092,8093,8840,8841,9620,9621,10432,10433,11276,11277,12152,12153,13060,13061,14000,1,14001,14972,14973,15976,15977,17012,17013,18080,18081,19180,19181,
19913,19912,18797,18796,17713,17712,16661,16660,15641,15640,14653,0,14652,13697,13696,12773,12772,11881,11880,11021,11020,10193,10192,9397,9396,8633,8632,0,7901,7900,7201,7200,6531,6533,6535,6537,6539,6541,6543,6545,6547,6549,6551,0,6553,6555,6557,6559,6561,6563,6565,6567,6569,6571,6573,6575,6577,6579,6581,0,6583,6585,6587,6589,6591,6593,6595,6597,6599,6601,6603,6605,6607,6609,6611,0,6613,6615,6617,6619,6621,6623,6625,6627,6629,6631,6633,6635,6637,6639,6641,0,6643,6645,6647,6649,6651,6653,6655,6657,6659,6661,6663,6665,6667,6669,6671,0,6673,6675,6677,6679,6681,6683,6685,6687,6689,6691,6693,6695,6697,7378,7379,0,8094,8095,8842,8843,9622,9623,10434,10435,11278,11279,12154,12155,13062,13063,14002,0,14003,14974,14975,15978,15979,17014,17015,18082,18083,19182,19183,
19911,19910,18795,18794,17711,17710,16659,16658,15639,15638,14651,1,14650,13695,13694,12771,12770,11879,11878,11019,11018,10191,10190,9395,9394,8631,8630,1,7899,7898,7199,7198,6530,6532,6534,6536,6538,6540,6542,6544,6546,6548,6550,1,6552,6554,6556,6558,6560,6562,6564,6566,6568,6570,6572,6574,6576,6578,6580,1,6582,6584,6586,6588,6590,6592,6594,6596,6598,6600,6602,6604,6606,6608,6610,1,6612,6614,6616,6618,6620,6622,6624,6626,6628,6630,6632,6634,6636,6638,6640,1,6642,6644,6646,6648,6650,6652,6654,6656,6658,6660,6662,6664,6666,6668,6670,1,6672,6674,6676,6678,6680,6682,6684,6686,6688,6690,6692,6694,6696,7380,7381,1,8096,8097,8844,8845,9624,9625,10436,10437,11280,11281,12156,12157,13064,13065,14004,1,14005,14976,14977,15980,15981,17016,17017,18084,18085,19184,19185,
19909,19908,18793,18792,17709,17708,16657,16656,15637,15636,14649,0,14648,13693,13692,12769,12768,11877,11876,11017,11016,10189,10188,9393,9392,8629,8628,0,7897,7896,7197,7196,6529,6528,5891,5893,5895,5897,5899,5901,5903,5905,5907,0,5909,5911,5913,5915,5917,5919,5921,5923,5925,5927,5929,5931,5933,5935,5937,0,5939,5941,5943,5945,5947,5949,5951,5953,5955,5957,5959,5961,5963,5965,5967,0,5969,5971,5973,5975,5977,5979,5981,5983,5985,5987,5989,5991,5993,5995,5997,0,5999,6001,6003,6005,6007,6009,6011,6013,6015,6017,6019,6021,6023,6025,6027,0,6029,6031,6033,6035,6037,6039,6041,6043,6045,6047,6049,6698,6699,7382,7383,0,8098,8099,8846,8847,9626,9627,10438,10439,11282,11283,12158,12159,13066,13067,14006,0,14007,14978,14979,15982,15983,17018,17019,18086,18087,19186,19187,
19907,19906,18791,18790,17707,17706,16655,16654,15635,15634,14647,1,14646,13691,13690,12767,12766,11875,11874,11015,11014,10187,10186,9391,9390,8627,8626,1,7895,7894,7195,7194,6527,6526,5890,5892,5894,5896,5898,5900,5902,5904,5906,1,5908,5910,5912,5914,5916,5918,5920,5922,5924,5926,5928,5930,5932,5934,5936,1,5938,5940,5942,5944,5946,5948,5950,5952,5954,5956,5958,5960,5962,5964,5966,1,5968,5970,5972,5974,5976,5978,5980,5982,5984,5986,5988,5990,5992,5994,5996,1,5998,6000,6002,6004,6006,6008,6010,6012,6014,6016,6018,6020,6022,6024,6026,1,6028,6030,6032,6034,6036,6038,6040,6042,6044,6046,6048,6700,6701,7384,7385,1,8100,8101,8848,8849,9628,9629,10440,10441,11284,11285,12160,12161,13068,13069,14008,1,14009,14980,14981,15984,15985,17020,17021,18088,18089,19188,19189,
19905,19904,18789,18788,17705,17704,16653,16652,15633,15632,14645,0,14644,13689,13688,12765,12764,11873,11872,11013,11012,10185,10184,9389,9388,8625,8624,0,7893,7892,7193,7192,6525,6524,5889,5888,5283,5285,5287,5289,5291,5293,5295,0,5297,5299,5301,5303,5305,5307,5309,5311,5313,5315,5317,5319,5321,5323,5325,0,5327,5329,5331,5333,5335,5337,5339,5341,5343,5345,5347,5349,5351,5353,5355,0,5357,5359,5361,5363,5365,5367,5369,5371,5373,5375,5377,5379,5381,5383,5385,0,5387,5389,5391,5393,5395,5397,5399,5401,5403,5405,5407,5409,5411,5413,5415,0,5417,5419,5421,5423,5425,5427,5429,5431,5433,6050,6051,6702,6703,7386,7387,0,8102,8103,8850,8851,9630,9631,10442,10443,11286,11287,12162,12163,13070,13071,14010,0,14011,14982,14983,15986,15987,17022,17023,18090,18091,19190,19191,
19903,19902,18787,18786,17703,17702,16651,16650,15631,15630,14643,1,14642,13687,13686,12763,12762,11871,11870,11011,11010,10183,10182,9387,9386,8623,8622,1,7891,7890,7191,7190,6523,6522,5887,5886,5282,5284,5286,5288,5290,5292,5294,1,5296,5298,5300,5302,5304,5306,5308,5310,5312,5314,5316,5318,5320,5322,5324,1,5326,5328,5330,5332,5334,5336,5338,5340,5342,5344,5346,5348,5350,5352,5354,1,5356,5358,5360,5362,5364,5366,5368,5370,5372,5374,5376,5378,5380,5382,5384,1,5386,5388,5390,5392,5394,5396,5398,5400,5402,5404,5406,5408,5410,5412,5414,1,5416,5418,5420,5422,5424,5426,5428,5430,5432,6052,6053,6704,6705,7388,7389,1,8104,8105,8852,8853,9632,9633,10444,10445,11288,11289,12164,12165,13072,13073,14012,1,14013,14984,14985,15988,15989,17024,17025,18092,18093,19192,19193,
19901,19900,18785,18784,17701,17700,16649,16648,15629,15628,14641,0,14640,13685,13684,12761,12760,11869,11868,11009,11008,10181,10180,9385,9384,8621,8620,0,7889,7888,7189,7188,6521,6520,5885,5884,5281,5280,4707,4709,4711,4713,4715,0,4717,4719,4721,4723,4725,4727,4729,4731,4733,4735,4737,4739,4741,4743,4745,0,4747,4749,4751,4753,4755,4757,4759,4761,4763,4765,4767,4769,4771,4773,4775,0,4777,4779,4781,4783,4785,4787,4789,4791,4793,4795,4797,4799,4801,4803,4805,0,4807,4809,4811,4813,4815,4817,4819,4821,4823,4825,4827,4829,4831,4833,4835,0,4837,4839,4841,4843,4845,4847,4849,5434,5435,6054,6055,6706,6707,7390,7391,0,8106,8107,8854,8855,9634,9635,10446,10447,11290,11291,12166,12167,13074,13075,14014,0,14015,14986,14987,15990,15991,17026,17027,18094,18095,19194,19195,
19899,19898,18783,18782,17699,17698,16647,16646,15627,15626,14639,1,14638,13683,13682,12759,12758,11867,11866,11007,11006,10179,10178,9383,9382,8619,8618,1,7887,7886,7187,7186,6519,6518,5883,5882,5279,5278,4706,4708,4710,4712,4714,1,4716,4718,4720,4722,4724,4726,4728,4730,4732,4734,4736,4738,4740,4742,4744,1,4746,4748,4750,4752,4754,4756,4758,4760,4762,4764,4766,4768,4770,4772,4774,1,4776,4778,4780,4782,4784,4786,4788,4790,4792,4794,4796,4798,4800,4802,4804,1,4806,4808,4810,4812,4814,4816,4818,4820,4822,4824,4826,4828,4830,4832,4834,1,4836,4838,4840,4842,4844,4846,4848,5436,5437,6056,6057,6708,6709,7392,7393,1,8108,8109,8856,8857,9636,9637,10448,10449,11292,11293,12168,12169,13076,13077,14016,1,14017,14988,14989,15992,15993,17028,17029,18096,18097,19196,19197,
19897,19896,18781,18780,17697,17696,16645,16644,15625,15624,14637,0,14636,13681,13680,12757,12756,11865,11864,11005,11004,10177,10176,9381,9380,8617,8616,0,7885,7884,7185,7184,6517,6516,5881,5880,5277,5276,4705,4704,4163,4165,4167,0,4169,4171,4173,4175,4177,4179,4181,4183,4185,4187,4189,4191,4193,4195,4197,0,4199,4201,4203,4205,4207,4209,4211,4213,4215,4217,4219,4221,4223,4225,4227,0,4229,4231,4233,4235,4237,4239,4241,4243,4245,4247,4249,4251,4253,4255,4257,0,4259,4261,4263,4265,4267,4269,4271,4273,4275,4277,4279,4281,4283,4285,4287,0,4289,4291,4293,4295,4297,4850,4851,5438,5439,6058,6059,6710,6711,7394,7395,0,8110,8111,8858,8859,9638,9639,10450,10451,11294,11295,12170,12171,13078,13079,14018,0,14019,14990,14991,15994,15995,17030,17031,18098,18099,19198,19199,
19895,19894,18779,18778,17695,17694,16643,16642,15623,15622,14635,1,14634,13679,13678,12755,12754,11863,11862,11003,11002,10175,10174,9379,9378,8615,8614,1,7883,7882,7183,7182,6515,6514,5879,5878,5275,5274,4703,4702,4162,4164,4166,1,4168,4170,4172,4174,4176,4178,4180,4182,4184,4186,4188,4190,4192,4194,4196,1,4198,4200,4202,4204,4206,4208,4210,4212,4214,4216,4218,4220,4222,4224,4226,1,4228,4230,4232,4234,4236,4238,4240,4242,4244,4246,4248,4250,4252,4254,4256,1,4258,4260,4262,4264,4266,4268,4270,4272,4274,4276,4278,4280,4282,4284,4286,1,4288,4290,4292,4294,4296,4852,4853,5440,5441,6060,6061,6712,6713,7396,7397,1,8112,8113,8860,8861,9640,9641,10452,10453,11296,11297,12172,12173,13080,13081,14020,1,14021,14992,14993,15996,15997,17032,17033,18100,18101,19200,19201,
19893,19892,18777,18776,17693,17692,16641,16640,15621,15620,14633,0,14632,13677,13676,12753,12752,11861,11860,11001,11000,10173,10172,9377,9376,8613,8612,0,7881,7880,7181,7180,6513,6512,5877,5876,5273,5272,4701,4700,4161,4160,3651,0,3653,3655,3657,3659,3661,3663,3665,3667,3669,3671,3673,3675,3677,3679,3681,0,3683,3685,3687,3689,3691,3693,3695,3697,3699,3701,3703,3705,3707,3709,3711,0,3713,3715,3717,3719,3721,3723,3725,3727,3729,3731,3733,3735,3737,3739,3741,0,3743,3745,3747,3749,3751,3753,3755,3757,3759,3761,3763,3765,3767,3769,3771,0,3773,3775,3777,4298,4299,4854,4855,5442,5443,6062,6063,6714,6715,7398,7399,0,8114,8115,8862,8863,9642,9643,10454,10455,11298,11299,12174,12175,13082,13083,14022,0,14023,14994,14995,15998,15999,17034,17035,18102,18103,19202,19203,
19891,19890,18775,18774,17691,17690,16639,16638,15619,15618,14631,1,14630,13675,13674,12751,12750,11859,11858,10999,10998,10171,10170,9375,9374,8611,8610,1,7879,7878,7179,7178,6511,6510,5875,5874,5271,5270,4699,4698,4159,4158,3650,1,3652,3654,3656,3658,3660,3662,3664,3666,3668,3670,3672,3674,3676,3678,3680,1,3682,3684,3686,3688,3690,3692,3694,3696,3698,3700,3702,3704,3706,3708,3710,1,3712,3714,3716,3718,3720,3722,3724,3726,3728,3730,3732,3734,3736,3738,3740,1,3742,3744,3746,3748,3750,3752,3754,3756,3758,3760,3762,3764,3766,3768,3770,1,3772,3774,3776,4300,4301,4856,4857,5444,5445,6064,6065,6716,6717,7400,7401,1,8116,8117,8864,8865,9644,9645,10456,10457,11300,11301,12176,12177,13084,13085,14024,1,14025,14996,14997,16000,16001,17036,17037,18104,18105,19204,19205,
19889,19888,18773,18772,17689,17688,16637,16636,15617,15616,14629,0,14628,13673,13672,12749,12748,11857,11856,10997,10996,10169,10168,9373,9372,8609,8608,0,7877,7876,7177,7176,6509,6508,5873,5872,5269,5268,4697,4696,4157,4156,3649,0,3648,3171,3173,3175,3177,3179,3181,3183,3185,3187,3189,3191,3193,3195,3197,0,3199,3201,3203,3205,3207,3209,3211,3213,3215,3217,3219,3221,3223,3225,3227,0,3229,3231,3233,3235,3237,3239,3241,3243,3245,3247,3249,3251,3253,3255,3257,0,3259,3261,3263,3265,3267,3269,3271,3273,3275,3277,3279,3281,3283,3285,3287,0,3289,3778,3779,4302,4303,4858,4859,5446,5447,6066,6067,6718,6719,7402,7403,0,8118,8119,8866,8867,9646,9647,10458,10459,11302,11303,12178,12179,13086,13087,14026,0,14027,14998,14999,16002,16003,17038,17039,18106,18107,19206,19207,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,
19887,19886,18771,18770,17687,17686,16635,16634,15615,15614,14627,0,14626,13671,13670,12747,12746,11855,11854,10995,10994,10167,10166,9371,9370,8607,8606,0,7875,7874,7175,7174,6507,6506,5871,5870,5267,5266,4695,4694,4155,4154,3647,0,3646,3170,3172,3174,3176,3178,3180,3182,3184,3186,3188,3190,3192,3194,3196,0,3198,3200,3202,3204,3206,3208,3210,3212,3214,3216,3218,3220,3222,3224,3226,0,3228,3230,3232,3234,3236,3238,3240,3242,3244,3246,3248,3250,3252,3254,3256,0,3258,3260,3262,3264,3266,3268,3270,3272,3274,3276,3278,3280,3282,3284,3286,0,3288,3780,3781,4304,4305,4860,4861,5448,5449,6068,6069,6720,6721,7404,7405,0,8120,8121,8868,8869,9648,9649,10460,10461,11304,11305,12180,12181,13088,13089,14028,0,14029,15000,15001,16004,16005,17040,17041,18108,18109,19208,19209,
19885,19884,18769,18768,17685,17684,16633,16632,15613,15612,14625,1,14624,13669,13668,12745,12744,11853,11852,10993,10992,10165,10164,9369,9368,8605,8604,1,7873,7872,7173,7172,6505,6504,5869,5868,5265,5264,4693,4692,4153,4152,3645,1,3644,3169,3168,2723,2725,2727,2729,2731,2733,2735,2737,2739,2741,2743,2745,1,2747,2749,2751,2753,2755,2757,2759,2761,2763,2765,2767,2769,2771,2773,2775,1,2777,2779,2781,2783,2785,2787,2789,2791,2793,2795,2797,2799,2801,2803,2805,1,2807,2809,2811,2813,2815,2817,2819,2821,2823,2825,2827,2829,2831,2833,3290,1,3291,3782,3783,4306,4307,4862,4863,5450,5451,6070,6071,6722,6723,7406,7407,1,8122,8123,8870,8871,9650,9651,10462,10463,11306,11307,12182,12183,13090,13091,14030,1,14031,15002,15003,16006,16007,17042,17043,18110,18111,19210,19211,
19883,19882,18767,18766,17683,17682,16631,16630,15611,15610,14623,0,14622,13667,13666,12743,12742,11851,11850,10991,10990,10163,10162,9367,9366,8603,8602,0,7871,7870,7171,7170,6503,6502,5867,5866,5263,5262,4691,4690,4151,4150,3643,0,3642,3167,3166,2722,2724,2726,2728,2730,2732,2734,2736,2738,2740,2742,2744,0,2746,2748,2750,2752,2754,2756,2758,2760,2762,2764,2766,2768,2770,2772,2774,0,2776,2778,2780,2782,2784,2786,2788,2790,2792,2794,2796,2798,2800,2802,2804,0,2806,2808,2810,2812,2814,2816,2818,2820,2822,2824,2826,2828,2830,2832,3292,0,3293,3784,3785,4308,4309,4864,4865,5452,5453,6072,6073,6724,6725,7408,7409,0,8124,8125,8872,8873,9652,9653,10464,10465,11308,11309,12184,12185,13092,13093,14032,0,14033,15004,15005,16008,16009,17044,17045,18112,18113,19212,19213,
19881,19880,18765,18764,17681,17680,16629,16628,15609,15608,14621,1,14620,13665,13664,12741,12740,11849,11848,10989,10988,10161,10160,9365,9364,8601,8600,1,7869,7868,7169,7168,6501,6500,5865,5864,5261,5260,4689,4688,4149,4148,3641,1,3640,3165,3164,2721,2720,2307,2309,2311,2313,2315,2317,2319,2321,2323,2325,1,2327,2329,2331,2333,2335,2337,2339,2341,2343,2345,2347,2349,2351,2353,2355,1,2357,2359,2361,2363,2365,2367,2369,2371,2373,2375,2377,2379,2381,2383,2385,1,2387,2389,2391,2393,2395,2397,2399,2401,2403,2405,2407,2409,2834,2835,3294,1,3295,3786,3787,4310,4311,4866,4867,5454,5455,6074,6075,6726,6727,7410,7411,1,8126,8127,8874,8875,9654,9655,10466,10467,11310,11311,12186,12187,13094,13095,14034,1,14035,15006,15007,16010,16011,17046,17047,18114,18115,19214,19215,
19879,19878,18763,18762,17679,17678,16627,16626,15607,15606,14619,0,14618,13663,13662,12739,12738,11847,11846,10987,10986,10159,10158,9363,9362,8599,8598,0,7867,7866,7167,7166,6499,6498,5863,5862,5259,5258,4687,4686,4147,4146,3639,0,3638,3163,3162,2719,2718,2306,2308,2310,2312,2314,2316,2318,2320,2322,2324,0,2326,2328,2330,2332,2334,2336,2338,2340,2342,2344,2346,2348,2350,2352,2354,0,2356,2358,2360,2362,2364,2366,2368,2370,2372,2374,2376,2378,2380,2382,2384,0,2386,2388,2390,2392,2394,2396,2398,2400,2402,2404,2406,2408,2836,2837,3296,0,3297,3788,3789,4312,4313,4868,4869,5456,5457,6076,6077,6728,6729,7412,7413,0,8128,8129,8876,8877,9656,9657,10468,10469,11312,11313,12188,12189,13096,13097,14036,0,14037,15008,15009,16012,16013,17048,17049,18116,18117,19216,19217,
19877,19876,18761,18760,17677,17676,16625,16624,15605,15604,14617,1,14616,13661,13660,12737,12736,11845,11844,10985,10984,10157,10156,9361,9360,8597,8596,1,7865,7864,7165,7164,6497,6496,5861,5860,5257,5256,4685,4684,4145,4144,3637,1,3636,3161,3160,2717,2716,2305,2304,1923,1925,1927,1929,1931,1933,1935,1937,1,1939,1941,1943,1945,1947,1949,1951,1953,1955,1957,1959,1961,1963,1965,1967,1,1969,1971,1973,1975,1977,1979,1981,1983,1985,1987,1989,1991,1993,1995,1997,1,1999,2001,2003,2005,2007,2009,2011,2013,2015,2017,2410,2411,2838,2839,3298,1,3299,3790,3791,4314,4315,4870,4871,5458,5459,6078,6079,6730,6731,7414,7415,1,8130,8131,8878,8879,9658,9659,10470,10471,11314,11315,12190,12191,13098,13099,14038,1,14039,15010,15011,16014,16015,17050,17051,18118,18119,19218,19219,
19875,19874,18759,18758,17675,17674,16623,16622,15603,15602,14615,0,14614,13659,13658,12735,12734,11843,11842,10983,10982,10155,10154,9359,9358,8595,8594,0,7863,7862,7163,7162,6495,6494,5859,5858,5255,5254,4683,4682,4143,4142,3635,0,3634,3159,3158,2715,2714,2303,2302,1922,1924,1926,1928,1930,1932,1934,1936,0,1938,1940,1942,1944,1946,1948,1950,1952,1954,1956,1958,1960,1962,1964,1966,0,1968,1970,1972,1974,1976,1978,1980,1982,1984,1986,1988,1990,1992,1994,1996,0,1998,2000,2002,2004,2006,2008,2010,2012,2014,2016,2412,2413,2840,2841,3300,0,3301,3792,3793,4316,4317,4872,4873,5460,5461,6080,6081,6732,6733,7416,7417,0,8132,8133,8880,8881,9660,9661,10472,10473,11316,11317,12192,12193,13100,13101,14040,0,14041,15012,15013,16016,16017,17052,17053,18120,18121,19220,19221,
19873,19872,18757,18756,17673,17672,16621,16620,15601,15600,14613,1,14612,13657,13656,12733,12732,11841,11840,10981,10980,10153,10152,9357,9356,8593,8592,1,7861,7860,7161,7160,6493,6492,5857,5856,5253,5252,4681,4680,4141,4140,3633,1,3632,3157,3156,2713,2712,2301,2300,1921,1920,1571,1573,1575,1577,1579,1581,1,1583,1585,1587,1589,1591,1593,1595,1597,1599,1601,1603,1605,1607,1609,1611,1,1613,1615,1617,1619,1621,1623,1625,1627,1629,1631,1633,1635,1637,1639,1641,1,1643,1645,1647,1649,1651,1653,1655,1657,2018,2019,2414,2415,2842,2843,3302,1,3303,3794,3795,4318,4319,4874,4875,5462,5463,6082,6083,6734,6735,7418,7419,1,8134,8135,8882,8883,9662,9663,10474,10475,11318,11319,12194,12195,13102,13103,14042,1,14043,15014,15015,16018,16019,17054,17055,18122,18123,19222,19223,
19871,19870,18755,18754,17671,17670,16619,16618,15599,15598,14611,0,14610,13655,13654,12731,12730,11839,11838,10979,10978,10151,10150,9355,9354,8591,8590,0,7859,7858,7159,7158,6491,6490,5855,5854,5251,5250,4679,4678,4139,4138,3631,0,3630,3155,3154,2711,2710,2299,2298,1919,1918,1570,1572,1574,1576,1578,1580,0,1582,1584,1586,1588,1590,1592,1594,1596,1598,1600,1602,1604,1606,1608,1610,0,1612,1614,1616,1618,1620,1622,1624,1626,1628,1630,1632,1634,1636,1638,1640,0,1642,1644,1646,1648,1650,1652,1654,1656,2020,2021,2416,2417,2844,2845,3304,0,3305,3796,3797,4320,4321,4876,4877,5464,5465,6084,6085,6736,6737,7420,7421,0,8136,8137,8884,8885,9664,9665,10476,10477,11320,11321,12196,12197,13104,13105,14044,0,14045,15016,15017,16020,16021,17056,17057,18124,18125,19224,19225,
19869,19868,18753,18752,17669,17668,16617,16616,15597,15596,14609,1,14608,13653,13652,12729,12728,11837,11836,10977,10976,10149,10148,9353,9352,8589,8588,1,7857,7856,7157,7156,6489,6488,5853,5852,5249,5248,4677,4676,4137,4136,3629,1,3628,3153,3152,2709,2708,2297,2296,1917,1916,1569,1568,1251,1253,1255,1257,1,1259,1261,1263,1265,1267,1269,1271,1273,1275,1277,1279,1281,1283,1285,1287,1,1289,1291,1293,1295,1297,1299,1301,1303,1305,1307,1309,1311,1313,1315,1317,1,1319,1321,1323,1325,1327,1329,1658,1659,2022,2023,2418,2419,2846,2847,3306,1,3307,3798,3799,4322,4323,4878,4879,5466,5467,6086,6087,6738,6739,7422,7423,1,8138,8139,8886,8887,9666,9667,10478,10479,11322,11323,12198,12199,13106,13107,14046,1,14047,15018,15019,16022,16023,17058,17059,18126,18127,19226,19227,
19867,19866,18751,18750,17667,17666,16615,16614,15595,15594,14607,0,14606,13651,13650,12727,12726,11835,11834,10975,10974,10147,10146,9351,9350,8587,8586,0,7855,7854,7155,7154,6487,6486,5851,5850,5247,5246,4675,4674,4135,4134,3627,0,3626,3151,3150,2707,2706,2295,2294,1915,1914,1567,1566,1250,1252,1254,1256,0,1258,1260,1262,1264,1266,1268,1270,1272,1274,1276,1278,1280,1282,1284,1286,0,1288,1290,1292,1294,1296,1298,1300,1302,1304,1306,1308,1310,1312,1314,1316,0,1318,1320,1322,1324,1326,1328,1660,1661,2024,2025,2420,2421,2848,2849,3308,0,3309,3800,3801,4324,4325,4880,4881,5468,5469,6088,6089,6740,6741,7424,7425,0,8140,8141,8888,8889,9668,9669,10480,10481,11324,11325,12200,12201,13108,13109,14048,0,14049,15020,15021,16024,16025,17060,17061,18128,18129,19228,19229,
19865,19864,18749,18748,17665,17664,16613,16612,15593,15592,14605,1,14604,13649,13648,12725,12724,11833,11832,10973,10972,10145,10144,9349,9348,8585,8584,1,7853,7852,7153,7152,6485,6484,5849,5848,5245,5244,4673,4672,4133,4132,3625,1,3624,3149,3148,2705,2704,2293,2292,1913,1912,1565,1564,1249,1248,963,965,1,967,969,971,973,975,977,979,981,983,985,987,989,991,993,995,1,997,999,1001,1003,1005,1007,1009,1011,1013,1015,1017,1019,1021,1023,1025,1,1027,1029,1031,1033,1330,1331,1662,1663,2026,2027,2422,2423,2850,2851,3310,1,3311,3802,3803,4326,4327,4882,4883,5470,5471,6090,6091,6742,6743,7426,7427,1,8142,8143,8890,8891,9670,9671,10482,10483,11326,11327,12202,12203,13110,13111,14050,1,14051,15022,15023,16026,16027,17062,17063,18130,18131,19230,19231,
19863,19862,18747,18746,17663,17662,16611,16610,15591,15590,14603,0,14602,13647,13646,12723,12722,11831,11830,10971,10970,10143,10142,9347,9346,8583,8582,0,7851,7850,7151,7150,6483,6482,5847,5846,5243,5242,4671,4670,4131,4130,3623,0,3622,3147,3146,2703,2702,2291,2290,1911,1910,1563,1562,1247,1246,962,964,0,966,968,970,972,974,976,978,980,982,984,986,988,990,992,994,0,996,998,1000,1002,1004,1006,1008,1010,1012,1014,1016,1018,1020,1022,1024,0,1026,1028,1030,1032,1332,1333,1664,1665,2028,2029,2424,2425,2852,2853,3312,0,3313,3804,3805,4328,4329,4884,4885,5472,5473,6092,6093,6744,6745,7428,7429,0,8144,8145,8892,8893,9672,9673,10484,10485,11328,11329,12204,12205,13112,13113,14052,0,14053,15024,15025,16028,16029,17064,17065,18132,18133,19232,19233,
19861,19860,18745,18744,17661,17660,16609,16608,15589,15588,14601,1,14600,13645,13644,12721,12720,11829,11828,10969,10968,10141,10140,9345,9344,8581,8580,1,7849,7848,7149,7148,6481,6480,5845,5844,5241,5240,4669,4668,4129,4128,3621,1,3620,3145,3144,2701,2700,2289,2288,1909,1908,1561,1560,1245,1244,961,960,1,707,709,711,713,715,717,719,721,723,725,727,729,731,733,735,1,737,739,741,743,745,747,749,751,753,755,757,759,761,763,765,1,767,769,1034,1035,1334,1335,1666,1667,2030,2031,2426,2427,2854,2855,3314,1,3315,3806,3807,4330,4331,4886,4887,5474,5475,6094,6095,6746,6747,7430,7431,1,8146,8147,8894,8895,9674,9675,10486,10487,11330,11331,12206,12207,13114,13115,14054,1,14055,15026,15027,16030,16031,17066,17067,18134,18135,19234,19235,
19859,19858,18743,18742,17659,17658,16607,16606,15587,15586,14599,0,14598,13643,13642,12719,12718,11827,11826,10967,10966,10139,10138,9343,9342,8579,8578,0,7847,7846,7147,7146,6479,6478,5843,5842,5239,5238,4667,4666,4127,4126,3619,0,3618,3143,3142,2699,2698,2287,2286,1907,1906,1559,1558,1243,1242,959,958,0,706,708,710,712,714,716,718,720,722,724,726,728,730,732,734,0,736,738,740,742,744,746,748,750,752,754,756,758,760,762,764,0,766,768,1036,1037,1336,1337,1668,1669,2032,2033,2428,2429,2856,2857,3316,0,3317,3808,3809,4332,4333,4888,4889,5476,5477,6096,6097,6748,6749,7432,7433,0,8148,8149,8896,8897,9676,9677,10488,10489,11332,11333,12208,12209,13116,13117,14056,0,14057,15028,15029,16032,16033,17068,17069,18136,18137,19236,19237,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,
19857,19856,18741,18740,17657,17656,16605,16604,15585,15584,14597,0,14596,13641,13640,12717,12716,11825,11824,10965,10964,10137,10136,9341,9340,8577,8576,0,7845,7844,7145,7144,6477,6476,5841,5840,5237,5236,4665,4664,4125,4124,3617,0,3616,3141,3140,2697,2696,2285,2284,1905,1904,1557,1556,1241,1240,957,956,0,705,704,483,485,487,489,491,493,495,497,499,501,503,505,507,0,509,511,513,515,517,519,521,523,525,527,529,531,533,535,537,0,770,771,1038,1039,1338,1339,1670,1671,2034,2035,2430,2431,2858,2859,3318,0,3319,3810,3811,4334,4335,4890,4891,5478,5479,6098,6099,6750,6751,7434,7435,0,8150,8151,8898,8899,9678,9679,10490,10491,11334,11335,12210,12211,13118,13119,14058,0,14059,15030,15031,16034,16035,17070,17071,18138,18139,19238,19239,
19855,19854,18739,18738,17655,17654,16603,16602,15583,15582,14595,1,14594,13639,13638,12715,12714,11823,11822,10963,10962,10135,10134,9339,9338,8575,8574,1,7843,7842,7143,7142,6475,6474,5839,5838,5235,5234,4663,4662,4123,4122,3615,1,3614,3139,3138,2695,2694,2283,2282,1903,1902,1555,1554,1239,1238,955,954,1,703,702,482,484,486,488,490,492,494,496,498,500,502,504,506,1,508,510,512,514,516,518,520,522,524,526,528,530,532,534,536,1,772,773,1040,1041,1340,1341,1672,1673,2036,2037,2432,2433,2860,2861,3320,1,3321,3812,3813,4336,4337,4892,4893,5480,5481,6100,6101,6752,6753,7436,7437,1,8152,8153,8900,8901,9680,9681,10492,10493,11336,11337,12212,12213,13120,13121,14060,1,14061,15032,15033,16036,16037,17072,17073,18140,18141,19240,19241,
19853,19852,18737,18736,17653,17652,16601,16600,15581,15580,14593,0,14592,13637,13636,12713,12712,11821,11820,10961,10960,10133,10132,9337,9336,8573,8572,0,7841,7840,7141,7140,6473,6472,5837,5836,5233,5232,4661,4660,4121,4120,3613,0,3612,3137,3136,2693,2692,2281,2280,1901,1900,1553,1552,1237,1236,953,952,0,701,700,481,480,291,293,295,297,299,301,303,305,307,309,311,0,313,315,317,319,321,323,325,327,329,331,333,335,337,538,539,0,774,775,1042,1043,1342,1343,1674,1675,2038,2039,2434,2435,2862,2863,3322,0,3323,3814,3815,4338,4339,4894,4895,5482,5483,6102,6103,6754,6755,7438,7439,0,8154,8155,8902,8903,9682,9683,10494,10495,11338,11339,12214,12215,13122,13123,14062,0,14063,15034,15035,16038,16039,17074,17075,18142,18143,19242,19243,
19851,19850,18735,18734,17651,17650,16599,16598,15579,15578,14591,1,14590,13635,13634,12711,12710,11819,11818,10959,10958,10131,10130,9335,9334,8571,8570,1,7839,7838,7139,7138,6471,6470,5835,5834,5231,5230,4659,4658,4119,4118,3611,1,3610,3135,3134,2691,2690,2279,2278,1899,1898,1551,1550,1235,1234,951,950,1,699,698,479,478,290,292,294,296,298,300,302,304,306,308,310,1,312,314,316,318,320,322,324,326,328,330,332,334,336,540,541,1,776,777,1044,1045,1344,1345,1676,1677,2040,2041,2436,2437,2864,2865,3324,1,3325,3816,3817,4340,4341,4896,4897,5484,5485,6104,6105,6756,6757,7440,7441,1,8156,8157,8904,8905,9684,9685,10496,10497,11340,11341,12216,12217,13124,13125,14064,1,14065,15036,15037,16040,16041,17076,17077,18144,18145,19244,19245,
19849,19848,18733,18732,17649,17648,16597,16596,15577,15576,14589,0,14588,13633,13632,12709,12708,11817,11816,10957,10956,10129,10128,9333,9332,8569,8568,0,7837,7836,7137,7136,6469,6468,5833,5832,5229,5228,4657,4656,4117,4116,3609,0,3608,3133,3132,2689,2688,2277,2276,1897,1896,1549,1548,1233,1232,949,948,0,697,696,477,476,289,288,131,133,135,137,139,141,143,145,147,0,149,151,153,155,157,159,161,163,165,167,169,338,339,542,543,0,778,779,1046,1047,1346,1347,1678,1679,2042,2043,2438,2439,2866,2867,3326,0,3327,3818,3819,4342,4343,4898,4899,5486,5487,6106,6107,6758,6759,7442,7443,0,8158,8159,8906,8907,9686,9687,10498,10499,11342,11343,12218,12219,13126,13127,14066,0,14067,15038,15039,16042,16043,17078,17079,18146,18147,19246,19247,
19847,19846,18731,18730,17647,17646,16595,16594,15575,15574,14587,1,14586,13631,13630,12707,12706,11815,11814,10955,10954,10127,10126,9331,9330,8567,8566,1,7835,7834,7135,7134,6467,6466,5831,5830,5227,5226,4655,4654,4115,4114,3607,1,3606,3131,3130,2687,2686,2275,2274,1895,1894,1547,1546,1231,1230,947,946,1,695,694,475,474,287,286,130,132,134,136,138,140,142,144,146,1,148,150,152,154,156,158,160,162,164,166,168,340,341,544,545,1,780,781,1048,1049,1348,1349,1680,1681,2044,2045,2440,2441,2868,2869,3328,1,3329,3820,3821,4344,4345,4900,4901,5488,5489,6108,6109,6760,6761,7444,7445,1,8160,8161,8908,8909,9688,9689,10500,10501,11344,11345,12220,12221,13128,13129,14068,1,14069,15040,15041,16044,16045,17080,17081,18148,18149,19248,19249,
19845,19844,18729,18728,17645,17644,16593,16592,15573,15572,14585,0,14584,13629,13628,12705,12704,11813,11812,10953,10952,10125,10124,9329,9328,8565,8564,0,7833,7832,7133,7132,6465,6464,5829,5828,5225,5224,4653,4652,4113,4112,3605,0,3604,3129,3128,2685,2684,2273,2272,1893,1892,1545,1544,1229,1228,945,944,0,693,692,473,472,285,284,129,128,3,5,7,9,11,13,15,0,17,19,21,23,25,27,29,31,33,170,171,342,343,546,547,0,782,783,1050,1051,1350,1351,1682,1683,2046,2047,2442,2443,2870,2871,3330,0,3331,3822,3823,4346,4347,4902,4903,5490,5491,6110,6111,6762,6763,7446,7447,0,8162,8163,8910,8911,9690,9691,10502,10503,11346,11347,12222,12223,13130,13131,14070,0,14071,15042,15043,16046,16047,17082,17083,18150,18151,19250,19251,
19843,19842,18727,18726,17643,17642,16591,16590,15571,15570,14583,1,14582,13627,13626,12703,12702,11811,11810,10951,10950,10123,10122,9327,9326,8563,8562,1,7831,7830,7131,7130,6463,6462,5827,5826,5223,5222,4651,4650,4111,4110,3603,1,3602,3127,3126,2683,2682,2271,2270,1891,1890,1543,1542,1227,1226,943,942,1,691,690,471,470,283,282,127,126,2,4,6,8,10,12,14,1,16,18,20,22,24,26,28,30,32,172,173,344,345,548,549,1,784,785,1052,1053,1352,1353,1684,1685,2048,2049,2444,2445,2872,2873,3332,1,3333,3824,3825,4348,4349,4904,4905,5492,5493,6112,6113,6764,6765,7448,7449,1,8164,8165,8912,8913,9692,9693,10504,10505,11348,11349,12224,12225,13132,13133,14072,1,14073,15044,15045,16048,16049,17084,17085,18152,18153,19252,19253,
19841,19840,18725,18724,17641,17640,16589,16588,15569,15568,14581,0,14580,13625,13624,12701,12700,11809,11808,10949,10948,10121,10120,9325,9324,8561,8560,0,7829,7828,7129,7128,6461,6460,5825,5824,5221,5220,4649,4648,4109,4108,3601,0,3600,3125,3124,2681,2680,2269,2268,1889,1888,1541,1540,1225,1224,941,940,0,689,688,469,468,281,280,125,124,1,1,20000,20001,20002,20003,20004,0,20005,20006,20007,20008,20009,0,1,34,35,174,175,346,347,550,551,0,786,787,1054,1055,1354,1355,1686,1687,2050,2051,2446,2447,2874,2875,3334,0,3335,3826,3827,4350,4351,4906,4907,5494,5495,6114,6115,6766,6767,7450,7451,0,8166,8167,8914,8915,9694,9695,10506,10507,11350,11351,12226,12227,13134,13135,14074,0,14075,15046,15047,16050,16051,17086,17087,18154,18155,19254,19255,
19839,19838,18723,18722,17639,17638,16587,16586,15567,15566,14579,1,14578,13623,13622,12699,12698,11807,11806,10947,10946,10119,10118,9323,9322,8559,8558,1,7827,7826,7127,7126,6459,6458,5823,5822,5219,5218,4647,4646,4107,4106,3599,1,3598,3123,3122,2679,2678,2267,2266,1887,1886,1539,1538,1223,1222,939,938,1,687,686,467,466,279,278,123,122,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,37,176,177,348,349,552,553,1,788,789,1056,1057,1356,1357,1688,1689,2052,2053,2448,2449,2876,2877,3336,1,3337,3828,3829,4352,4353,4908,4909,5496,5497,6116,6117,6768,6769,7452,7453,1,8168,8169,8916,8917,9696,9697,10508,10509,11352,11353,12228,12229,13136,13137,14076,1,14077,15048,15049,16052,16053,17088,17089,18156,18157,19256,19257,
19837,19836,18721,18720,17637,17636,16585,16584,15565,15564,14577,0,14576,13621,13620,12697,12696,11805,11804,10945,10944,10117,10116,9321,9320,8557,8556,0,7825,7824,7125,7124,6457,6456,5821,5820,5217,5216,4645,4644,4105,4104,3597,0,3596,3121,3120,2677,2676,2265,2264,1885,1884,1537,1536,1221,1220,937,936,0,685,684,465,464,277,276,121,120,20039,1,0,0,0,0,0,0,0,0,0,0,0,1,20010,38,39,178,179,350,351,554,555,0,790,791,1058,1059,1358,1359,1690,1691,2054,2055,2450,2451,2878,2879,3338,0,3339,3830,3831,4354,4355,4910,4911,5498,5499,6118,6119,6770,6771,7454,7455,0,8170,8171,8918,8919,9698,9699,10510,10511,11354,11355,12230,12231,13138,13139,14078,0,14079,15050,15051,16054,16055,17090,17091,18158,18159,19258,19259,
19835,19834,18719,18718,17635,17634,16583,16582,15563,15562,14575,1,14574,13619,13618,12695,12694,11803,11802,10943,10942,10115,10114,9319,9318,8555,8554,1,7823,7822,7123,7122,6455,6454,5819,5818,5215,5214,4643,4642,4103,4102,3595,1,3594,3119,3118,2675,2674,2263,2262,1883,1882,1535,1534,1219,1218,935,934,1,683,682,463,462,275,274,119,118,20038,1,0,1,1,1,1,1,1,1,1,1,0,1,20011,40,41,180,181,352,353,556,557,1,792,793,1060,1061,1360,1361,1692,1693,2056,2057,2452,2453,2880,2881,3340,1,3341,3832,3833,4356,4357,4912,4913,5500,5501,6120,6121,6772,6773,7456,7457,1,8172,8173,8920,8921,9700,9701,10512,10513,11356,11357,12232,12233,13140,13141,14080,1,14081,15052,15053,16056,16057,17092,17093,18160,18161,19260,19261,
19833,19832,18717,18716,17633,17632,16581,16580,15561,15560,14573,0,14572,13617,13616,12693,12692,11801,11800,10941,10940,10113,10112,9317,9316,8553,8552,0,7821,7820,7121,7120,6453,6452,5817,5816,5213,5212,4641,4640,4101,4100,3593,0,3592,3117,3116,2673,2672,2261,2260,1881,1880,1533,1532,1217,1216,933,932,0,681,680,461,460,273,272,117,116,20037,1,0,1,0,0,0,0,0,0,0,1,0,1,20012,42,43,182,183,354,355,558,559,0,794,795,1062,1063,1362,1363,1694,1695,2058,2059,2454,2455,2882,2883,3342,0,3343,3834,3835,4358,4359,4914,4915,5502,5503,6122,6123,6774,6775,7458,7459,0,8174,8175,8922,8923,9702,9703,10514,10515,11358,11359,12234,12235,13142,13143,14082,0,14083,15054,15055,16058,16059,17094,17095,18162,18163,19262,19263,
19831,19830,18715,18714,17631,17630,16579,16578,15559,15558,14571,1,14570,13615,13614,12691,12690,11799,11798,10939,10938,10111,10110,9315,9314,8551,8550,1,7819,7818,7119,7118,6451,6450,5815,5814,5211,5210,4639,4638,4099,4098,3591,1,3590,3115,3114,2671,2670,2259,2258,1879,1878,1531,1530,1215,1214,931,930,1,679,678,459,458,271,270,115,114,20036,1,0,1,0,1,1,1,1,1,0,1,0,1,20013,44,45,184,185,356,357,560,561,1,796,797,1064,1065,1364,1365,1696,1697,2060,2061,2456,2457,2884,2885,3344,1,3345,3836,3837,4360,4361,4916,4917,5504,5505,6124,6125,6776,6777,7460,7461,1,8176,8177,8924,8925,9704,9705,10516,10517,11360,11361,12236,12237,13144,13145,14084,1,14085,15056,15057,16060,16061,17096,17097,18164,18165,19264,19265,
19829,19828,18713,18712,17629,17628,16577,16576,15557,15556,14569,0,14568,13613,13612,12689,12688,11797,11796,10937,10936,10109,10108,9313,9312,8549,8548,0,7817,7816,7117,7116,6449,6448,5813,5812,5209,5208,4637,4636,4097,4096,3589,0,3588,3113,3112,2669,2668,2257,2256,1877,1876,1529,1528,1213,1212,929,928,0,677,676,457,456,269,268,113,112,20035,1,0,1,0,1,0,0,0,1,0,1,0,1,20014,46,47,186,187,358,359,562,563,0,798,799,1066,1067,1366,1367,1698,1699,2062,2063,2458,2459,2886,2887,3346,0,3347,3838,3839,4362,4363,4918,4919,5506,5507,6126,6127,6778,6779,7462,7463,0,8178,8179,8926,8927,9706,9707,10518,10519,11362,11363,12238,12239,13146,13147,14086,0,14087,15058,15059,16062,16063,17098,17099,18166,18167,19266,19267,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,
19827,19826,18711,18710,17627,17626,16575,16574,15555,15554,14567,0,14566,13611,13610,12687,12686,11795,11794,10935,10934,10107,10106,9311,9310,8547,8546,0,7815,7814,7115,7114,6447,6446,5811,5810,5207,5206,4635,4634,4095,4094,3587,0,3586,3111,3110,2667,2666,2255,2254,1875,1874,1527,1526,1211,1210,927,926,0,675,674,455,454,267,266,111,110,20034,1,0,1,0,1,0,0,0,1,0,1,0,1,20015,48,49,188,189,360,361,564,565,0,800,801,1068,1069,1368,1369,1700,1701,2064,2065,2460,2461,2888,2889,3348,0,3349,3840,3841,4364,4365,4920,4921,5508,5509,6128,6129,6780,6781,7464,7465,0,8180,8181,8928,8929,9708,9709,10520,10521,11364,11365,12240,12241,13148,13149,14088,0,14089,15060,15061,16064,16065,17100,17101,18168,18169,19268,19269,
19825,19824,18709,18708,17625,17624,16573,16572,15553,15552,14565,1,14564,13609,13608,12685,12684,11793,11792,10933,10932,10105,10104,9309,9308,8545,8544,1,7813,7812,7113,7112,6445,6444,5809,5808,5205,5204,4633,4632,4093,4092,3585,1,3584,3109,3108,2665,2664,2253,2252,1873,1872,1525,1524,1209,1208,925,924,1,673,672,453,452,265,264,109,108,20033,1,0,1,0,1,1,1,1,1,0,1,0,1,20016,50,51,190,191,362,363,566,567,1,802,803,1070,1071,1370,1371,1702,1703,2066,2067,2462,2463,2890,2891,3350,1,3351,3842,3843,4366,4367,4922,4923,5510,5511,6130,6131,6782,6783,7466,7467,1,8182,8183,8930,8931,9710,9711,10522,10523,11366,11367,12242,12243,13150,13151,14090,1,14091,15062,15063,16066,16067,17102,17103,18170,18171,19270,19271,
19823,19822,18707,18706,17623,17622,16571,16570,15551,15550,14563,0,14562,13607,13606,12683,12682,11791,11790,10931,10930,10103,10102,9307,9306,8543,8542,0,7811,7810,7111,7110,6443,6442,5807,5806,5203,5202,4631,4630,4091,4090,3583,0,3582,3107,3106,2663,2662,2251,2250,1871,1870,1523,1522,1207,1206,923,922,0,671,670,451,450,263,262,107,106,20032,1,0,1,0,0,0,0,0,0,0,1,0,1,20017,52,53,192,193,364,365,568,569,0,804,805,1072,1073,1372,1373,1704,1705,2068,2069,2464,2465,2892,2893,3352,0,3353,3844,3845,4368,4369,4924,4925,5512,5513,6132,6133,6784,6785,7468,7469,0,8184,8185,8932,8933,9712,9713,10524,10525,11368,11369,12244,12245,13152,13153,14092,0,14093,15064,15065,16068,16069,17104,17105,18172,18173,19272,19273,
19821,19820,18705,18704,17621,17620,16569,16568,15549,15548,14561,1,14560,13605,13604,12681,12680,11789,11788,10929,10928,10101,10100,9305,9304,8541,8540,1,7809,7808,7109,7108,6441,6440,5805,5804,5201,5200,4629,4628,4089,4088,3581,1,3580,3105,3104,2661,2660,2249,2248,1869,1868,1521,1520,1205,1204,921,920,1,669,668,449,448,261,260,105,104,20031,1,0,1,1,1,1,1,1,1,1,1,0,1,20018,54,55,194,195,366,367,570,571,1,806,807,1074,1075,1374,1375,1706,1707,2070,2071,2466,2467,2894,2895,3354,1,3355,3846,3847,4370,4371,4926,4927,5514,5515,6134,6135,6786,6787,7470,7471,1,8186,8187,8934,8935,9714,9715,10526,10527,11370,11371,12246,12247,13154,13155,14094,1,14095,15066,15067,16070,16071,17106,17107,18174,18175,19274,19275,
19819,19818,18703,18702,17619,17618,16567,16566,15547,15546,14559,0,14558,13603,13602,12679,12678,11787,11786,10927,10926,10099,10098,9303,9302,8539,8538,0,7807,7806,7107,7106,6439,6438,5803,5802,5199,5198,4627,4626,4087,4086,3579,0,3578,3103,3102,2659,2658,2247,2246,1867,1866,1519,1518,1203,1202,919,918,0,667,666,447,446,259,258,103,102,20030,1,0,0,0,0,0,0,0,0,0,0,0,1,20019,56,57,196,197,368,369,572,573,0,808,809,1076,1077,1376,1377,1708,1709,2072,2073,2468,2469,2896,2897,3356,0,3357,3848,3849,4372,4373,4928,4929,5516,5517,6136,6137,6788,6789,7472,7473,0,8188,8189,8936,8937,9716,9717,10528,10529,11372,11373,12248,12249,13156,13157,14096,0,14097,15068,15069,16072,16073,17108,17109,18176,18177,19276,19277,
19817,19816,18701,18700,17617,17616,16565,16564,15545,15544,14557,1,14556,13601,13600,12677,12676,11785,11784,10925,10924,10097,10096,9301,9300,8537,8536,1,7805,7804,7105,7104,6437,6436,5801,5800,5197,5196,4625,4624,4085,4084,3577,1,3576,3101,3100,2657,2656,2245,2244,1865,1864,1517,1516,1201,1200,917,916,1,665,664,445,444,257,256,101,100,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,58,59,198,199,370,371,574,575,1,810,811,1078,1079,1378,1379,1710,1711,2074,2075,2470,2471,2898,2899,3358,1,3359,3850,3851,4374,4375,4930,4931,5518,5519,6138,6139,6790,6791,7474,7475,1,8190,8191,8938,8939,9718,9719,10530,10531,11374,11375,12250,12251,13158,13159,14098,1,14099,15070,15071,16074,16075,17110,17111,18178,18179,19278,19279,
19815,19814,18699,18698,17615,17614,16563,16562,15543,15542,14555,0,14554,13599,13598,12675,12674,11783,11782,10923,10922,10095,10094,9299,9298,8535,8534,0,7803,7802,7103,7102,6435,6434,5799,5798,5195,5194,4623,4622,4083,4082,3575,0,3574,3099,3098,2655,2654,2243,2242,1863,1862,1515,1514,1199,1198,915,914,0,663,662,443,442,255,254,99,98,0,0,20029,20028,20027,20026,20025,0,20024,20023,20022,20021,20020,0,0,60,61,200,201,372,373,576,577,0,812,813,1080,1081,1380,1381,1712,1713,2076,2077,2472,2473,2900,2901,3360,0,3361,3852,3853,4376,4377,4932,4933,5520,5521,6140,6141,6792,6793,7476,7477,0,8192,8193,8940,8941,9720,9721,10532,10533,11376,11377,12252,12253,13160,13161,14100,0,14101,15072,15073,16076,16077,17112,17113,18180,18181,19280,19281,
19813,19812,18697,18696,17613,17612,16561,16560,15541,15540,14553,1,14552,13597,13596,12673,12672,11781,11780,10921,10920,10093,10092,9297,9296,8533,8532,1,7801,7800,7101,7100,6433,6432,5797,5796,5193,5192,4621,4620,4081,4080,3573,1,3572,3097,3096,2653,2652,2241,2240,1861,1860,1513,1512,1197,1196,913,912,1,661,660,441,440,253,252,96,94,92,90,88,86,84,82,80,1,78,76,74,72,70,68,66,62,63,202,203,374,375,578,579,1,814,815,1082,1083,1382,1383,1714,1715,2078,2079,2474,2475,2902,2903,3362,1,3363,3854,3855,4378,4379,4934,4935,5522,5523,6142,6143,6794,6795,7478,7479,1,8194,8195,8942,8943,9722,9723,10534,10535,11378,11379,12254,12255,13162,13163,14102,1,14103,15074,15075,16078,16079,17114,17115,18182,18183,19282,19283,
19811,19810,18695,18694,17611,17610,16559,16558,15539,15538,14551,0,14550,13595,13594,12671,12670,11779,11778,10919,10918,10091,10090,9295,9294,8531,8530,0,7799,7798,7099,7098,6431,6430,5795,5794,5191,5190,4619,4618,4079,4078,3571,0,3570,3095,3094,2651,2650,2239,2238,1859,1858,1511,1510,1195,1194,911,910,0,659,658,439,438,251,250,97,95,93,91,89,87,85,83,81,0,79,77,75,73,71,69,67,64,65,204,205,376,377,580,581,0,816,817,1084,1085,1384,1385,1716,1717,2080,2081,2476,2477,2904,2905,3364,0,3365,3856,3857,4380,4381,4936,4937,5524,5525,6144,6145,6796,6797,7480,7481,0,8196,8197,8944,8945,9724,9725,10536,10537,11380,11381,12256,12257,13164,13165,14104,0,14105,15076,15077,16080,16081,17116,17117,18184,18185,19284,19285,
19809,19808,18693,18692,17609,17608,16557,16556,15537,15536,14549,1,14548,13593,13592,12669,12668,11777,11776,10917,10916,10089,10088,9293,9292,8529,8528,1,7797,7796,7097,7096,6429,6428,5793,5792,5189,5188,4617,4616,4077,4076,3569,1,3568,3093,3092,2649,2648,2237,2236,1857,1856,1509,1508,1193,1192,909,908,1,657,656,437,436,248,246,244,242,240,238,236,234,232,230,228,1,226,224,222,220,218,216,214,212,210,206,207,378,379,582,583,1,818,819,1086,1087,1386,1387,1718,1719,2082,2083,2478,2479,2906,2907,3366,1,3367,3858,3859,4382,4383,4938,4939,5526,5527,6146,6147,6798,6799,7482,7483,1,8198,8199,8946,8947,9726,9727,10538,10539,11382,11383,12258,12259,13166,13167,14106,1,14107,15078,15079,16082,16083,17118,17119,18186,18187,19286,19287,
19807,19806,18691,18690,17607,17606,16555,16554,15535,15534,14547,0,14546,13591,13590,12667,12666,11775,11774,10915,10914,10087,10086,9291,9290,8527,8526,0,7795,7794,7095,7094,6427,6426,5791,5790,5187,5186,4615,4614,4075,4074,3567,0,3566,3091,3090,2647,2646,2235,2234,1855,1854,1507,1506,1191,1190,907,906,0,655,654,435,434,249,247,245,243,241,239,237,235,233,231,229,0,227,225,223,221,219,217,215,213,211,208,209,380,381,584,585,0,820,821,1088,1089,1388,1389,1720,1721,2084,2085,2480,2481,2908,2909,3368,0,3369,3860,3861,4384,4385,4940,4941,5528,5529,6148,6149,6800,6801,7484,7485,0,8200,8201,8948,8949,9728,9729,10540,10541,11384,11385,12260,12261,13168,13169,14108,0,14109,15080,15081,16084,16085,17120,17121,18188,18189,19288,19289,
19805,19804,18689,18688,17605,17604,16553,16552,15533,15532,14545,1,14544,13589,13588,12665,12664,11773,11772,10913,10912,10085,10084,9289,9288,8525,8524,1,7793,7792,7093,7092,6425,6424,5789,5788,5185,5184,4613,4612,4073,4072,3565,1,3564,3089,3088,2645,2644,2233,2232,1853,1852,1505,1504,1189,1188,905,904,1,653,652,432,430,428,426,424,422,420,418,416,414,412,410,408,1,406,404,402,400,398,396,394,392,390,388,386,382,383,586,587,1,822,823,1090,1091,1390,1391,1722,1723,2086,2087,2482,2483,2910,2911,3370,1,3371,3862,3863,4386,4387,4942,4943,5530,5531,6150,6151,6802,6803,7486,7487,1,8202,8203,8950,8951,9730,9731,10542,10543,11386,11387,12262,12263,13170,13171,14110,1,14111,15082,15083,16086,16087,17122,17123,18190,18191,19290,19291,
19803,19802,18687,18686,17603,17602,16551,16550,15531,15530,14543,0,14542,13587,13586,12663,12662,11771,11770,10911,10910,10083,10082,9287,9286,8523,8522,0,7791,7790,7091,7090,6423,6422,5787,5786,5183,5182,4611,4610,4071,4070,3563,0,3562,3087,3086,2643,2642,2231,2230,1851,1850,1503,1502,1187,1186,903,902,0,651,650,433,431,429,427,425,423,421,419,417,415,413,411,409,0,407,405,403,401,399,397,395,393,391,389,387,384,385,588,589,0,824,825,1092,1093,1392,1393,1724,1725,2088,2089,2484,2485,2912,2913,3372,0,3373,3864,3865,4388,4389,4944,4945,5532,5533,6152,6153,6804,6805,7488,7489,0,8204,8205,8952,8953,9732,9733,10544,10545,11388,11389,12264,12265,13172,13173,14112,0,14113,15084,15085,16088,16089,17124,17125,18192,18193,19292,19293,
19801,19800,18685,18684,17601,17600,16549,16548,15529,15528,14541,1,14540,13585,13584,12661,12660,11769,11768,10909,10908,10081,10080,9285,9284,8521,8520,1,7789,7788,7089,7088,6421,6420,5785,5784,5181,5180,4609,4608,4069,4068,3561,1,3560,3085,3084,2641,2640,2229,2228,1849,1848,1501,1500,1185,1184,901,900,1,648,646,644,642,640,638,636,634,632,630,628,626,624,622,620,1,618,616,614,612,610,608,606,604,602,600,598,596,594,590,591,1,826,827,1094,1095,1394,1395,1726,1727,2090,2091,2486,2487,2914,2915,3374,1,3375,3866,3867,4390,4391,4946,4947,5534,5535,6154,6155,6806,6807,7490,7491,1,8206,8207,8954,8955,9734,9735,10546,10547,11390,11391,12266,12267,13174,13175,14114,1,14115,15086,15087,16090,16091,17126,17127,18194,18195,19294,19295,
19799,19798,18683,18682,17599,17598,16547,16546,15527,15526,14539,0,14538,13583,13582,12659,12658,11767,11766,10907,10906,10079,10078,9283,9282,8519,8518,0,7787,7786,7087,7086,6419,6418,5783,5782,5179,5178,4607,4606,4067,4066,3559,0,3558,3083,3082,2639,2638,2227,2226,1847,1846,1499,1498,1183,1182,899,898,0,649,647,645,643,641,639,637,635,633,631,629,627,625,623,621,0,619,617,615,613,611,609,607,605,603,601,599,597,595,592,593,0,828,829,1096,1097,1396,1397,1728,1729,2092,2093,2488,2489,2916,2917,3376,0,3377,3868,3869,4392,4393,4948,4949,5536,5537,6156,6157,6808,6809,7492,7493,0,8208,8209,8956,8957,9736,9737,10548,10549,11392,11393,12268,12269,13176,13177,14116,0,14117,15088,15089,16092,16093,17128,17129,18196,18197,19296,19297,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,
19797,19796,18681,18680,17597,17596,16545,16544,15525,15524,14537,0,14536,13581,13580,12657,12656,11765,11764,10905,10904,10077,10076,9281,9280,8517,8516,0,7785,7784,7085,7084,6417,6416,5781,5780,5177,5176,4605,4604,4065,4064,3557,0,3556,3081,3080,2637,2636,2225,2224,1845,1844,1497,1496,1181,1180,896,894,0,892,890,888,886,884,882,880,878,876,874,872,870,868,866,864,0,862,860,858,856,854,852,850,848,846,844,842,840,838,836,834,0,830,831,1098,1099,1398,1399,1730,1731,2094,2095,2490,2491,2918,2919,3378,0,3379,3870,3871,4394,4395,4950,4951,5538,5539,6158,6159,6810,6811,7494,7495,0,8210,8211,8958,8959,9738,9739,10550,10551,11394,11395,12270,12271,13178,13179,14118,0,14119,15090,15091,16094,16095,17130,17131,18198,18199,19298,19299,
19795,19794,18679,18678,17595,17594,16543,16542,15523,15522,14535,1,14534,13579,13578,12655,12654,11763,11762,10903,10902,10075,10074,9279,9278,8515,8514,1,7783,7782,7083,7082,6415,6414,5779,5778,5175,5174,4603,4602,4063,4062,3555,1,3554,3079,3078,2635,2634,2223,2222,1843,1842,1495,1494,1179,1178,897,895,1,893,891,889,887,885,883,881,879,877,875,873,871,869,867,865,1,863,861,859,857,855,853,851,849,847,845,843,841,839,837,835,1,832,833,1100,1101,1400,1401,1732,1733,2096,2097,2492,2493,2920,2921,3380,1,3381,3872,3873,4396,4397,4952,4953,5540,5541,6160,6161,6812,6813,7496,7497,1,8212,8213,8960,8961,9740,9741,10552,10553,11396,11397,12272,12273,13180,13181,14120,1,14121,15092,15093,16096,16097,17132,17133,18200,18201,19300,19301,
19793,19792,18677,18676,17593,17592,16541,16540,15521,15520,14533,0,14532,13577,13576,12653,12652,11761,11760,10901,10900,10073,10072,9277,9276,8513,8512,0,7781,7780,7081,7080,6413,6412,5777,5776,5173,5172,4601,4600,4061,4060,3553,0,3552,3077,3076,2633,2632,2221,2220,1841,1840,1493,1492,1176,1174,1172,1170,0,1168,1166,1164,1162,1160,1158,1156,1154,1152,1150,1148,1146,1144,1142,1140,0,1138,1136,1134,1132,1130,1128,1126,1124,1122,1120,1118,1116,1114,1112,1110,0,1108,1106,1102,1103,1402,1403,1734,1735,2098,2099,2494,2495,2922,2923,3382,0,3383,3874,3875,4398,4399,4954,4955,5542,5543,6162,6163,6814,6815,7498,7499,0,8214,8215,8962,8963,9742,9743,10554,10555,11398,11399,12274,12275,13182,13183,14122,0,14123,15094,15095,16098,16099,17134,17135,18202,18203,19302,19303,
19791,19790,18675,18674,17591,17590,16539,16538,15519,15518,14531,1,14530,13575,13574,12651,12650,11759,11758,10899,10898,10071,10070,9275,9274,8511,8510,1,7779,7778,7079,7078,6411,6410,5775,5774,5171,5170,4599,4598,4059,4058,3551,1,3550,3075,3074,2631,2630,2219,2218,1839,1838,1491,1490,1177,1175,1173,1171,1,1169,1167,1165,1163,1161,1159,1157,1155,1153,1151,1149,1147,1145,1143,1141,1,1139,1137,1135,1133,1131,1129,1127,1125,1123,1121,1119,1117,1115,1113,1111,1,1109,1107,1104,1105,1404,1405,1736,1737,2100,2101,2496,2497,2924,2925,3384,1,3385,3876,3877,4400,4401,4956,4957,5544,5545,6164,6165,6816,6817,7500,7501,1,8216,8217,8964,8965,9744,9745,10556,10557,11400,11401,12276,12277,13184,13185,14124,1,14125,15096,15097,16100,16101,17136,17137,18204,18205,19304,19305,
19789,19788,18673,18672,17589,17588,16537,16536,15517,15516,14529,0,14528,13573,13572,12649,12648,11757,11756,10897,10896,10069,10068,9273,9272,8509,8508,0,7777,7776,7077,7076,6409,6408,5773,5772,5169,5168,4597,4596,4057,4056,3549,0,3548,3073,3072,2629,2628,2217,2216,1837,1836,1488,1486,1484,1482,1480,1478,0,1476,1474,1472,1470,1468,1466,1464,1462,1460,1458,1456,1454,1452,1450,1448,0,1446,1444,1442,1440,1438,1436,1434,1432,1430,1428,1426,1424,1422,1420,1418,0,1416,1414,1412,1410,1406,1407,1738,1739,2102,2103,2498,2499,2926,2927,3386,0,3387,3878,3879,4402,4403,4958,4959,5546,5547,6166,6167,6818,6819,7502,7503,0,8218,8219,8966,8967,9746,9747,10558,10559,11402,11403,12278,12279,13186,13187,14126,0,14127,15098,15099,16102,16103,17138,17139,18206,18207,19306,19307,
19787,19786,18671,18670,17587,17586,16535,16534,15515,15514,14527,1,14526,13571,13570,12647,12646,11755,11754,10895,10894,10067,10066,9271,9270,8507,8506,1,7775,7774,7075,7074,6407,6406,5771,5770,5167,5166,4595,4594,4055,4054,3547,1,3546,3071,3070,2627,2626,2215,2214,1835,1834,1489,1487,1485,1483,1481,1479,1,1477,1475,1473,1471,1469,1467,1465,1463,1461,1459,1457,1455,1453,1451,1449,1,1447,1445,1443,1441,1439,1437,1435,1433,1431,1429,1427,1425,1423,1421,1419,1,1417,1415,1413,1411,1408,1409,1740,1741,2104,2105,2500,2501,2928,2929,3388,1,3389,3880,3881,4404,4405,4960,4961,5548,5549,6168,6169,6820,6821,7504,7505,1,8220,8221,8968,8969,9748,9749,10560,10561,11404,11405,12280,12281,13188,13189,14128,1,14129,15100,15101,16104,16105,17140,17141,18208,18209,19308,19309,
19785,19784,18669,18668,17585,17584,16533,16532,15513,15512,14525,0,14524,13569,13568,12645,12644,11753,11752,10893,10892,10065,10064,9269,9268,8505,8504,0,7773,7772,7073,7072,6405,6404,5769,5768,5165,5164,4593,4592,4053,4052,3545,0,3544,3069,3068,2625,2624,2213,2212,1832,1830,1828,1826,1824,1822,1820,1818,0,1816,1814,1812,1810,1808,1806,1804,1802,1800,1798,1796,1794,1792,1790,1788,0,1786,1784,1782,1780,1778,1776,1774,1772,1770,1768,1766,1764,1762,1760,1758,0,1756,1754,1752,1750,1748,1746,1742,1743,2106,2107,2502,2503,2930,2931,3390,0,3391,3882,3883,4406,4407,4962,4963,5550,5551,6170,6171,6822,6823,7506,7507,0,8222,8223,8970,8971,9750,9751,10562,10563,11406,11407,12282,12283,13190,13191,14130,0,14131,15102,15103,16106,16107,17142,17143,18210,18211,19310,19311,
19783,19782,18667,18666,17583,17582,16531,16530,15511,15510,14523,1,14522,13567,13566,12643,12642,11751,11750,10891,10890,10063,10062,9267,9266,8503,8502,1,7771,7770,7071,7070,6403,6402,5767,5766,5163,5162,4591,4590,4051,4050,3543,1,3542,3067,3066,2623,2622,2211,2210,1833,1831,1829,1827,1825,1823,1821,1819,1,1817,1815,1813,1811,1809,1807,1805,1803,1801,1799,1797,1795,1793,1791,1789,1,1787,1785,1783,1781,1779,1777,1775,1773,1771,1769,1767,1765,1763,1761,1759,1,1757,1755,1753,1751,1749,1747,1744,1745,2108,2109,2504,2505,2932,2933,3392,1,3393,3884,3885,4408,4409,4964,4965,5552,5553,6172,6173,6824,6825,7508,7509,1,8224,8225,8972,8973,9752,9753,10564,10565,11408,11409,12284,12285,13192,13193,14132,1,14133,15104,15105,16108,16109,17144,17145,18212,18213,19312,19313,
19781,19780,18665,18664,17581,17580,16529,16528,15509,15508,14521,0,14520,13565,13564,12641,12640,11749,11748,10889,10888,10061,10060,9265,9264,8501,8500,0,7769,7768,7069,7068,6401,6400,5765,5764,5161,5160,4589,4588,4049,4048,3541,0,3540,3065,3064,2621,2620,2208,2206,2204,2202,2200,2198,2196,2194,2192,2190,0,2188,2186,2184,2182,2180,2178,2176,2174,2172,2170,2168,2166,2164,2162,2160,0,2158,2156,2154,2152,2150,2148,2146,2144,2142,2140,2138,2136,2134,2132,2130,0,2128,2126,2124,2122,2120,2118,2116,2114,2110,2111,2506,2507,2934,2935,3394,0,3395,3886,3887,4410,4411,4966,4967,5554,5555,6174,6175,6826,6827,7510,7511,0,8226,8227,8974,8975,9754,9755,10566,10567,11410,11411,12286,12287,13194,13195,14134,0,14135,15106,15107,16110,16111,17146,17147,18214,18215,19314,19315,
19779,19778,18663,18662,17579,17578,16527,16526,15507,15506,14519,1,14518,13563,13562,12639,12638,11747,11746,10887,10886,10059,10058,9263,9262,8499,8498,1,7767,7766,7067,7066,6399,6398,5763,5762,5159,5158,4587,4586,4047,4046,3539,1,3538,3063,3062,2619,2618,2209,2207,2205,2203,2201,2199,2197,2195,2193,2191,1,2189,2187,2185,2183,2181,2179,2177,2175,2173,2171,2169,2167,2165,2163,2161,1,2159,2157,2155,2153,2151,2149,2147,2145,2143,2141,2139,2137,2135,2133,2131,1,2129,2127,2125,2123,2121,2119,2117,2115,2112,2113,2508,2509,2936,2937,3396,1,3397,3888,3889,4412,4413,4968,4969,5556,5557,6176,6177,6828,6829,7512,7513,1,8228,8229,8976,8977,9756,9757,10568,10569,11412,11413,12288,12289,13196,13197,14136,1,14137,15108,15109,16112,16113,17148,17149,18216,18217,19316,19317,
19777,19776,18661,18660,17577,17576,16525,16524,15505,15504,14517,0,14516,13561,13560,12637,12636,11745,11744,10885,10884,10057,10056,9261,9260,8497,8496,0,7765,7764,7065,7064,6397,6396,5761,5760,5157,5156,4585,4584,4045,4044,3537,0,3536,3061,3060,2616,2614,2612,2610,2608,2606,2604,2602,2600,2598,2596,2594,0,2592,2590,2588,2586,2584,2582,2580,2578,2576,2574,2572,2570,2568,2566,2564,0,2562,2560,2558,2556,2554,2552,2550,2548,2546,2544,2542,2540,2538,2536,2534,0,2532,2530,2528,2526,2524,2522,2520,2518,2516,2514,2510,2511,2938,2939,3398,0,3399,3890,3891,4414,4415,4970,4971,5558,5559,6178,6179,6830,6831,7514,7515,0,8230,8231,8978,8979,9758,9759,10570,10571,11414,11415,12290,12291,13198,13199,14138,0,14139,15110,15111,16114,16115,17150,17151,18218,18219,19318,19319,
19775,19774,18659,18658,17575,17574,16523,16522,15503,15502,14515,1,14514,13559,13558,12635,12634,11743,11742,10883,10882,10055,10054,9259,9258,8495,8494,1,7763,7762,7063,7062,6395,6394,5759,5758,5155,5154,4583,4582,4043,4042,3535,1,3534,3059,3058,2617,2615,2613,2611,2609,2607,2605,2603,2601,2599,2597,2595,1,2593,2591,2589,2587,2585,2583,2581,2579,2577,2575,2573,2571,2569,2567,2565,1,2563,2561,2559,2557,2555,2553,2551,2549,2547,2545,2543,2541,2539,2537,2535,1,2533,2531,2529,2527,2525,2523,2521,2519,2517,2515,2512,2513,2940,2941,3400,1,3401,3892,3893,4416,4417,4972,4973,5560,5561,6180,6181,6832,6833,7516,7517,1,8232,8233,8980,8981,9760,9761,10572,10573,11416,11417,12292,12293,13200,13201,14140,1,14141,15112,15113,16116,16117,17152,17153,18220,18221,19320,19321,
19773,19772,18657,18656,17573,17572,16521,16520,15501,15500,14513,0,14512,13557,13556,12633,12632,11741,11740,10881,10880,10053,10052,9257,9256,8493,8492,0,7761,7760,7061,7060,6393,6392,5757,5756,5153,5152,4581,4580,4041,4040,3533,0,3532,3056,3054,3052,3050,3048,3046,3044,3042,3040,3038,3036,3034,3032,3030,0,3028,3026,3024,3022,3020,3018,3016,3014,3012,3010,3008,3006,3004,3002,3000,0,2998,2996,2994,2992,2990,2988,2986,2984,2982,2980,2978,2976,2974,2972,2970,0,2968,2966,2964,2962,2960,2958,2956,2954,2952,2950,2948,2946,2942,2943,3402,0,3403,3894,3895,4418,4419,4974,4975,5562,5563,6182,6183,6834,6835,7518,7519,0,8234,8235,8982,8983,9762,9763,10574,10575,11418,11419,12294,12295,13202,13203,14142,0,14143,15114,15115,16118,16119,17154,17155,18222,18223,19322,19323,
19771,19770,18655,18654,17571,17570,16519,16518,15499,15498,14511,1,14510,13555,13554,12631,12630,11739,11738,10879,10878,10051,10050,9255,9254,8491,8490,1,7759,7758,7059,7058,6391,6390,5755,5754,5151,5150,4579,4578,4039,4038,3531,1,3530,3057,3055,3053,3051,3049,3047,3045,3043,3041,3039,3037,3035,3033,3031,1,3029,3027,3025,3023,3021,3019,3017,3015,3013,3011,3009,3007,3005,3003,3001,1,2999,2997,2995,2993,2991,2989,2987,2985,2983,2981,2979,2977,2975,2973,2971,1,2969,2967,2965,2963,2961,2959,2957,2955,2953,2951,2949,2947,2944,2945,3404,1,3405,3896,3897,4420,4421,4976,4977,5564,5565,6184,6185,6836,6837,7520,7521,1,8236,8237,8984,8985,9764,9765,10576,10577,11420,11421,12296,12297,13204,13205,14144,1,14145,15116,15117,16120,16121,17156,17157,18224,18225,19324,19325,
19769,19768,18653,18652,17569,17568,16517,16516,15497,15496,14509,0,14508,13553,13552,12629,12628,11737,11736,10877,10876,10049,10048,9253,9252,8489,8488,0,7757,7756,7057,7056,6389,6388,5753,5752,5149,5148,4577,4576,4037,4036,3528,0,3526,3524,3522,3520,3518,3516,3514,3512,3510,3508,3506,3504,3502,3500,3498,0,3496,3494,3492,3490,3488,3486,3484,3482,3480,3478,3476,3474,3472,3470,3468,0,3466,3464,3462,3460,3458,3456,3454,3452,3450,3448,3446,3444,3442,3440,3438,0,3436,3434,3432,3430,3428,3426,3424,3422,3420,3418,3416,3414,3412,3410,3406,0,3407,3898,3899,4422,4423,4978,4979,5566,5567,6186,6187,6838,6839,7522,7523,0,8238,8239,8986,8987,9766,9767,10578,10579,11422,11423,12298,12299,13206,13207,14146,0,14147,15118,15119,16122,16123,17158,17159,18226,18227,19326,19327,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,
19767,19766,18651,18650,17567,17566,16515,16514,15495,15494,14507,0,14506,13551,13550,12627,12626,11735,11734,10875,10874,10047,10046,9251,9250,8487,8486,0,7755,7754,7055,7054,6387,6386,5751,5750,5147,5146,4575,4574,4035,4034,3529,0,3527,3525,3523,3521,3519,3517,3515,3513,3511,3509,3507,3505,3503,3501,3499,0,3497,3495,3493,3491,3489,3487,3485,3483,3481,3479,3477,3475,3473,3471,3469,0,3467,3465,3463,3461,3459,3457,3455,3453,3451,3449,3447,3445,3443,3441,3439,0,3437,3435,3433,3431,3429,3427,3425,3423,3421,3419,3417,3415,3413,3411,3408,0,3409,3900,3901,4424,4425,4980,4981,5568,5569,6188,6189,6840,6841,7524,7525,0,8240,8241,8988,8989,9768,9769,10580,10581,11424,11425,12300,12301,13208,13209,14148,0,14149,15120,15121,16124,16125,17160,17161,18228,18229,19328,19329,
19765,19764,18649,18648,17565,17564,16513,16512,15493,15492,14505,1,14504,13549,13548,12625,12624,11733,11732,10873,10872,10045,10044,9249,9248,8485,8484,1,7753,7752,7053,7052,6385,6384,5749,5748,5145,5144,4573,4572,4032,4030,4028,1,4026,4024,4022,4020,4018,4016,4014,4012,4010,4008,4006,4004,4002,4000,3998,1,3996,3994,3992,3990,3988,3986,3984,3982,3980,3978,3976,3974,3972,3970,3968,1,3966,3964,3962,3960,3958,3956,3954,3952,3950,3948,3946,3944,3942,3940,3938,1,3936,3934,3932,3930,3928,3926,3924,3922,3920,3918,3916,3914,3912,3910,3908,1,3906,3902,3903,4426,4427,4982,4983,5570,5571,6190,6191,6842,6843,7526,7527,1,8242,8243,8990,8991,9770,9771,10582,10583,11426,11427,12302,12303,13210,13211,14150,1,14151,15122,15123,16126,16127,17162,17163,18230,18231,19330,19331,
19763,19762,18647,18646,17563,17562,16511,16510,15491,15490,14503,0,14502,13547,13546,12623,12622,11731,11730,10871,10870,10043,10042,9247,9246,8483,8482,0,7751,7750,7051,7050,6383,6382,5747,5746,5143,5142,4571,4570,4033,4031,4029,0,4027,4025,4023,4021,4019,4017,4015,4013,4011,4009,4007,4005,4003,4001,3999,0,3997,3995,3993,3991,3989,3987,3985,3983,3981,3979,3977,3975,3973,3971,3969,0,3967,3965,3963,3961,3959,3957,3955,3953,3951,3949,3947,3945,3943,3941,3939,0,3937,3935,3933,3931,3929,3927,3925,3923,3921,3919,3917,3915,3913,3911,3909,0,3907,3904,3905,4428,4429,4984,4985,5572,5573,6192,6193,6844,6845,7528,7529,0,8244,8245,8992,8993,9772,9773,10584,10585,11428,11429,12304,12305,13212,13213,14152,0,14153,15124,15125,16128,16129,17164,17165,18232,18233,19332,19333,
19761,19760,18645,18644,17561,17560,16509,16508,15489,15488,14501,1,14500,13545,13544,12621,12620,11729,11728,10869,10868,10041,10040,9245,9244,8481,8480,1,7749,7748,7049,7048,6381,6380,5745,5744,5141,5140,4568,4566,4564,4562,4560,1,4558,4556,4554,4552,4550,4548,4546,4544,4542,4540,4538,4536,4534,4532,4530,1,4528,4526,4524,4522,4520,4518,4516,4514,4512,4510,4508,4506,4504,4502,4500,1,4498,4496,4494,4492,4490,4488,4486,4484,4482,4480,4478,4476,4474,4472,4470,1,4468,4466,4464,4462,4460,4458,4456,4454,4452,4450,4448,4446,4444,4442,4440,1,4438,4436,4434,4430,4431,4986,4987,5574,5575,6194,6195,6846,6847,7530,7531,1,8246,8247,8994,8995,9774,9775,10586,10587,11430,11431,12306,12307,13214,13215,14154,1,14155,15126,15127,16130,16131,17166,17167,18234,18235,19334,19335,
19759,19758,18643,18642,17559,17558,16507,16506,15487,15486,14499,0,14498,13543,13542,12619,12618,11727,11726,10867,10866,10039,10038,9243,9242,8479,8478,0,7747,7746,7047,7046,6379,6378,5743,5742,5139,5138,4569,4567,4565,4563,4561,0,4559,4557,4555,4553,4551,4549,4547,4545,4543,4541,4539,4537,4535,4533,4531,0,4529,4527,4525,4523,4521,4519,4517,4515,4513,4511,4509,4507,4505,4503,4501,0,4499,4497,4495,4493,4491,4489,4487,4485,4483,4481,4479,4477,4475,4473,4471,0,4469,4467,4465,4463,4461,4459,4457,4455,4453,4451,4449,4447,4445,4443,4441,0,4439,4437,4435,4432,4433,4988,4989,5576,5577,6196,6197,6848,6849,7532,7533,0,8248,8249,8996,8997,9776,9777,10588,10589,11432,11433,12308,12309,13216,13217,14156,0,14157,15128,15129,16132,16133,17168,17169,18236,18237,19336,19337,
19757,19756,18641,18640,17557,17556,16505,16504,15485,15484,14497,1,14496,13541,13540,12617,12616,11725,11724,10865,10864,10037,10036,9241,9240,8477,8476,1,7745,7744,7045,7044,6377,6376,5741,5740,5136,5134,5132,5130,5128,5126,5124,1,5122,5120,5118,5116,5114,5112,5110,5108,5106,5104,5102,5100,5098,5096,5094,1,5092,5090,5088,5086,5084,5082,5080,5078,5076,5074,5072,5070,5068,5066,5064,1,5062,5060,5058,5056,5054,5052,5050,5048,5046,5044,5042,5040,5038,5036,5034,1,5032,5030,5028,5026,5024,5022,5020,5018,5016,5014,5012,5010,5008,5006,5004,1,5002,5000,4998,4996,4994,4990,4991,5578,5579,6198,6199,6850,6851,7534,7535,1,8250,8251,8998,8999,9778,9779,10590,10591,11434,11435,12310,12311,13218,13219,14158,1,14159,15130,15131,16134,16135,17170,17171,18238,18239,19338,19339,
19755,19754,18639,18638,17555,17554,16503,16502,15483,15482,14495,0,14494,13539,13538,12615,12614,11723,11722,10863,10862,10035,10034,9239,9238,8475,8474,0,7743,7742,7043,7042,6375,6374,5739,5738,5137,5135,5133,5131,5129,5127,5125,0,5123,5121,5119,5117,5115,5113,5111,5109,5107,5105,5103,5101,5099,5097,5095,0,5093,5091,5089,5087,5085,5083,5081,5079,5077,5075,5073,5071,5069,5067,5065,0,5063,5061,5059,5057,5055,5053,5051,5049,5047,5045,5043,5041,5039,5037,5035,0,5033,5031,5029,5027,5025,5023,5021,5019,5017,5015,5013,5011,5009,5007,5005,0,5003,5001,4999,4997,4995,4992,4993,5580,5581,6200,6201,6852,6853,7536,7537,0,8252,8253,9000,9001,9780,9781,10592,10593,11436,11437,12312,12313,13220,13221,14160,0,14161,15132,15133,16136,16137,17172,17173,18240,18241,19340,19341,
19753,19752,18637,18636,17553,17552,16501,16500,15481,15480,14493,1,14492,13537,13536,12613,12612,11721,11720,10861,10860,10033,10032,9237,9236,8473,8472,1,7741,7740,7041,7040,6373,6372,5736,5734,5732,5730,5728,5726,5724,5722,5720,1,5718,5716,5714,5712,5710,5708,5706,5704,5702,5700,5698,5696,5694,5692,5690,1,5688,5686,5684,5682,5680,5678,5676,5674,5672,5670,5668,5666,5664,5662,5660,1,5658,5656,5654,5652,5650,5648,5646,5644,5642,5640,5638,5636,5634,5632,5630,1,5628,5626,5624,5622,5620,5618,5616,5614,5612,5610,5608,5606,5604,5602,5600,1,5598,5596,5594,5592,5590,5588,5586,5582,5583,6202,6203,6854,6855,7538,7539,1,8254,8255,9002,9003,9782,9783,10594,10595,11438,11439,12314,12315,13222,13223,14162,1,14163,15134,15135,16138,16139,17174,17175,18242,18243,19342,19343,
19751,19750,18635,18634,17551,17550,16499,16498,15479,15478,14491,0,14490,13535,13534,12611,12610,11719,11718,10859,10858,10031,10030,9235,9234,8471,8470,0,7739,7738,7039,7038,6371,6370,5737,5735,5733,5731,5729,5727,5725,5723,5721,0,5719,5717,5715,5713,5711,5709,5707,5705,5703,5701,5699,5697,5695,5693,5691,0,5689,5687,5685,5683,5681,5679,5677,5675,5673,5671,5669,5667,5665,5663,5661,0,5659,5657,5655,5653,5651,5649,5647,5645,5643,5641,5639,5637,5635,5633,5631,0,5629,5627,5625,5623,5621,5619,5617,5615,5613,5611,5609,5607,5605,5603,5601,0,5599,5597,5595,5593,5591,5589,5587,5584,5585,6204,6205,6856,6857,7540,7541,0,8256,8257,9004,9005,9784,9785,10596,10597,11440,11441,12316,12317,13224,13225,14164,0,14165,15136,15137,16140,16141,17176,17177,18244,18245,19344,19345,
19749,19748,18633,18632,17549,17548,16497,16496,15477,15476,14489,1,14488,13533,13532,12609,12608,11717,11716,10857,10856,10029,10028,9233,9232,8469,8468,1,7737,7736,7037,7036,6368,6366,6364,6362,6360,6358,6356,6354,6352,6350,6348,1,6346,6344,6342,6340,6338,6336,6334,6332,6330,6328,6326,6324,6322,6320,6318,1,6316,6314,6312,6310,6308,6306,6304,6302,6300,6298,6296,6294,6292,6290,6288,1,6286,6284,6282,6280,6278,6276,6274,6272,6270,6268,6266,6264,6262,6260,6258,1,6256,6254,6252,6250,6248,6246,6244,6242,6240,6238,6236,6234,6232,6230,6228,1,6226,6224,6222,6220,6218,6216,6214,6212,6210,6206,6207,6858,6859,7542,7543,1,8258,8259,9006,9007,9786,9787,10598,10599,11442,11443,12318,12319,13226,13227,14166,1,14167,15138,15139,16142,16143,17178,17179,18246,18247,19346,19347,
19747,19746,18631,18630,17547,17546,16495,16494,15475,15474,14487,0,14486,13531,13530,12607,12606,11715,11714,10855,10854,10027,10026,9231,9230,8467,8466,0,7735,7734,7035,7034,6369,6367,6365,6363,6361,6359,6357,6355,6353,6351,6349,0,6347,6345,6343,6341,6339,6337,6335,6333,6331,6329,6327,6325,6323,6321,6319,0,6317,6315,6313,6311,6309,6307,6305,6303,6301,6299,6297,6295,6293,6291,6289,0,6287,6285,6283,6281,6279,6277,6275,6273,6271,6269,6267,6265,6263,6261,6259,0,6257,6255,6253,6251,6249,6247,6245,6243,6241,6239,6237,6235,6233,6231,6229,0,6227,6225,6223,6221,6219,6217,6215,6213,6211,6208,6209,6860,6861,7544,7545,0,8260,8261,9008,9009,9788,9789,10600,10601,11444,11445,12320,12321,13228,13229,14168,0,14169,15140,15141,16144,16145,17180,17181,18248,18249,19348,19349,
19745,19744,18629,18628,17545,17544,16493,16492,15473,15472,14485,1,14484,13529,13528,12605,12604,11713,11712,10853,10852,10025,10024,9229,9228,8465,8464,1,7733,7732,7032,7030,7028,7026,7024,7022,7020,7018,7016,7014,7012,7010,7008,1,7006,7004,7002,7000,6998,6996,6994,6992,6990,6988,6986,6984,6982,6980,6978,1,6976,6974,6972,6970,6968,6966,6964,6962,6960,6958,6956,6954,6952,6950,6948,1,6946,6944,6942,6940,6938,6936,6934,6932,6930,6928,6926,6924,6922,6920,6918,1,6916,6914,6912,6910,6908,6906,6904,6902,6900,6898,6896,6894,6892,6890,6888,1,6886,6884,6882,6880,6878,6876,6874,6872,6870,6868,6866,6862,6863,7546,7547,1,8262,8263,9010,9011,9790,9791,10602,10603,11446,11447,12322,12323,13230,13231,14170,1,14171,15142,15143,16146,16147,17182,17183,18250,18251,19350,19351,
19743,19742,18627,18626,17543,17542,16491,16490,15471,15470,14483,0,14482,13527,13526,12603,12602,11711,11710,10851,10850,10023,10022,9227,9226,8463,8462,0,7731,7730,7033,7031,7029,7027,7025,7023,7021,7019,7017,7015,7013,7011,7009,0,7007,7005,7003,7001,6999,6997,6995,6993,6991,6989,6987,6985,6983,6981,6979,0,6977,6975,6973,6971,6969,6967,6965,6963,6961,6959,6957,6955,6953,6951,6949,0,6947,6945,6943,6941,6939,6937,6935,6933,6931,6929,6927,6925,6923,6921,6919,0,6917,6915,6913,6911,6909,6907,6905,6903,6901,6899,6897,6895,6893,6891,6889,0,6887,6885,6883,6881,6879,6877,6875,6873,6871,6869,6867,6864,6865,7548,7549,0,8264,8265,9012,9013,9792,9793,10604,10605,11448,11449,12324,12325,13232,13233,14172,0,14173,15144,15145,16148,16149,17184,17185,18252,18253,19352,19353,
19741,19740,18625,18624,17541,17540,16489,16488,15469,15468,14481,1,14480,13525,13524,12601,12600,11709,11708,10849,10848,10021,10020,9225,9224,8461,8460,1,7728,7726,7724,7722,7720,7718,7716,7714,7712,7710,7708,7706,7704,7702,7700,1,7698,7696,7694,7692,7690,7688,7686,7684,7682,7680,7678,7676,7674,7672,7670,1,7668,7666,7664,7662,7660,7658,7656,7654,7652,7650,7648,7646,7644,7642,7640,1,7638,7636,7634,7632,7630,7628,7626,7624,7622,7620,7618,7616,7614,7612,7610,1,7608,7606,7604,7602,7600,7598,7596,7594,7592,7590,7588,7586,7584,7582,7580,1,7578,7576,7574,7572,7570,7568,7566,7564,7562,7560,7558,7556,7554,7550,7551,1,8266,8267,9014,9015,9794,9795,10606,10607,11450,11451,12326,12327,13234,13235,14174,1,14175,15146,15147,16150,16151,17186,17187,18254,18255,19354,19355,
19739,19738,18623,18622,17539,17538,16487,16486,15467,15466,14479,0,14478,13523,13522,12599,12598,11707,11706,10847,10846,10019,10018,9223,9222,8459,8458,0,7729,7727,7725,7723,7721,7719,7717,7715,7713,7711,7709,7707,7705,7703,7701,0,7699,7697,7695,7693,7691,7689,7687,7685,7683,7681,7679,7677,7675,7673,7671,0,7669,7667,7665,7663,7661,7659,7657,7655,7653,7651,7649,7647,7645,7643,7641,0,7639,7637,7635,7633,7631,7629,7627,7625,7623,7621,7619,7617,7615,7613,7611,0,7609,7607,7605,7603,7601,7599,7597,7595,7593,7591,7589,7587,7585,7583,7581,0,7579,7577,7575,7573,7571,7569,7567,7565,7563,7561,7559,7557,7555,7552,7553,0,8268,8269,9016,9017,9796,9797,10608,10609,11452,11453,12328,12329,13236,13237,14176,0,14177,15148,15149,16152,16153,17188,17189,18256,18257,19356,19357,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,
19737,19736,18621,18620,17537,17536,16485,16484,15465,15464,14477,0,14476,13521,13520,12597,12596,11705,11704,10845,10844,10017,10016,9221,9220,8456,8454,0,8452,8450,8448,8446,8444,8442,8440,8438,8436,8434,8432,8430,8428,8426,8424,0,8422,8420,8418,8416,8414,8412,8410,8408,8406,8404,8402,8400,8398,8396,8394,0,8392,8390,8388,8386,8384,8382,8380,8378,8376,8374,8372,8370,8368,8366,8364,0,8362,8360,8358,8356,8354,8352,8350,8348,8346,8344,8342,8340,8338,8336,8334,0,8332,8330,8328,8326,8324,8322,8320,8318,8316,8314,8312,8310,8308,8306,8304,0,8302,8300,8298,8296,8294,8292,8290,8288,8286,8284,8282,8280,8278,8276,8274,0,8270,8271,9018,9019,9798,9799,10610,10611,11454,11455,12330,12331,13238,13239,14178,0,14179,15150,15151,16154,16155,17190,17191,18258,18259,19358,19359,
19735,19734,18619,18618,17535,17534,16483,16482,15463,15462,14475,1,14474,13519,13518,12595,12594,11703,11702,10843,10842,10015,10014,9219,9218,8457,8455,1,8453,8451,8449,8447,8445,8443,8441,8439,8437,8435,8433,8431,8429,8427,8425,1,8423,8421,8419,8417,8415,8413,8411,8409,8407,8405,8403,8401,8399,8397,8395,1,8393,8391,8389,8387,8385,8383,8381,8379,8377,8375,8373,8371,8369,8367,8365,1,8363,8361,8359,8357,8355,8353,8351,8349,8347,8345,8343,8341,8339,8337,8335,1,8333,8331,8329,8327,8325,8323,8321,8319,8317,8315,8313,8311,8309,8307,8305,1,8303,8301,8299,8297,8295,8293,8291,8289,8287,8285,8283,8281,8279,8277,8275,1,8272,8273,9020,9021,9800,9801,10612,10613,11456,11457,12332,12333,13240,13241,14180,1,14181,15152,15153,16156,16157,17192,17193,18260,18261,19360,19361,
19733,19732,18617,18616,17533,17532,16481,16480,15461,15460,14473,0,14472,13517,13516,12593,12592,11701,11700,10841,10840,10013,10012,9216,9214,9212,9210,0,9208,9206,9204,9202,9200,9198,9196,9194,9192,9190,9188,9186,9184,9182,9180,0,9178,9176,9174,9172,9170,9168,9166,9164,9162,9160,9158,9156,9154,9152,9150,0,9148,9146,9144,9142,9140,9138,9136,9134,9132,9130,9128,9126,9124,9122,9120,0,9118,9116,9114,9112,9110,9108,9106,9104,9102,9100,9098,9096,9094,9092,9090,0,9088,9086,9084,9082,9080,9078,9076,9074,9072,9070,9068,9066,9064,9062,9060,0,9058,9056,9054,9052,9050,9048,9046,9044,9042,9040,9038,9036,9034,9032,9030,0,9028,9026,9022,9023,9802,9803,10614,10615,11458,11459,12334,12335,13242,13243,14182,0,14183,15154,15155,16158,16159,17194,17195,18262,18263,19362,19363,
19731,19730,18615,18614,17531,17530,16479,16478,15459,15458,14471,1,14470,13515,13514,12591,12590,11699,11698,10839,10838,10011,10010,9217,9215,9213,9211,1,9209,9207,9205,9203,9201,9199,9197,9195,9193,9191,9189,9187,9185,9183,9181,1,9179,9177,9175,9173,9171,9169,9167,9165,9163,9161,9159,9157,9155,9153,9151,1,9149,9147,9145,9143,9141,9139,9137,9135,9133,9131,9129,9127,9125,9123,9121,1,9119,9117,9115,9113,9111,9109,9107,9105,9103,9101,9099,9097,9095,9093,9091,1,9089,9087,9085,9083,9081,9079,9077,9075,9073,9071,9069,9067,9065,9063,9061,1,9059,9057,9055,9053,9051,9049,9047,9045,9043,9041,9039,9037,9035,9033,9031,1,9029,9027,9024,9025,9804,9805,10616,10617,11460,11461,12336,12337,13244,13245,14184,1,14185,15156,15157,16160,16161,17196,17197,18264,18265,19364,19365,
19729,19728,18613,18612,17529,17528,16477,16476,15457,15456,14469,0,14468,13513,13512,12589,12588,11697,11696,10837,10836,10008,10006,10004,10002,10000,9998,0,9996,9994,9992,9990,9988,9986,9984,9982,9980,9978,9976,9974,9972,9970,9968,0,9966,9964,9962,9960,9958,9956,9954,9952,9950,9948,9946,9944,9942,9940,9938,0,9936,9934,9932,9930,9928,9926,9924,9922,9920,9918,9916,9914,9912,9910,9908,0,9906,9904,9902,9900,9898,9896,9894,9892,9890,9888,9886,9884,9882,9880,9878,0,9876,9874,9872,9870,9868,9866,9864,9862,9860,9858,9856,9854,9852,9850,9848,0,9846,9844,9842,9840,9838,9836,9834,9832,9830,9828,9826,9824,9822,9820,9818,0,9816,9814,9812,9810,9806,9807,10618,10619,11462,11463,12338,12339,13246,13247,14186,0,14187,15158,15159,16162,16163,17198,17199,18266,18267,19366,19367,
19727,19726,18611,18610,17527,17526,16475,16474,15455,15454,14467,1,14466,13511,13510,12587,12586,11695,11694,10835,10834,10009,10007,10005,10003,10001,9999,1,9997,9995,9993,9991,9989,9987,9985,9983,9981,9979,9977,9975,9973,9971,9969,1,9967,9965,9963,9961,9959,9957,9955,9953,9951,9949,9947,9945,9943,9941,9939,1,9937,9935,9933,9931,9929,9927,9925,9923,9921,9919,9917,9915,9913,9911,9909,1,9907,9905,9903,9901,9899,9897,9895,9893,9891,9889,9887,9885,9883,9881,9879,1,9877,9875,9873,9871,9869,9867,9865,9863,9861,9859,9857,9855,9853,9851,9849,1,9847,9845,9843,9841,9839,9837,9835,9833,9831,9829,9827,9825,9823,9821,9819,1,9817,9815,9813,9811,9808,9809,10620,10621,11464,11465,12340,12341,13248,13249,14188,1,14189,15160,15161,16164,16165,17200,17201,18268,18269,19368,19369,
19725,19724,18609,18608,17525,17524,16473,16472,15453,15452,14465,0,14464,13509,13508,12585,12584,11693,11692,10832,10830,10828,10826,10824,10822,10820,10818,0,10816,10814,10812,10810,10808,10806,10804,10802,10800,10798,10796,10794,10792,10790,10788,0,10786,10784,10782,10780,10778,10776,10774,10772,10770,10768,10766,10764,10762,10760,10758,0,10756,10754,10752,10750,10748,10746,10744,10742,10740,10738,10736,10734,10732,10730,10728,0,10726,10724,10722,10720,10718,10716,10714,10712,10710,10708,10706,10704,10702,10700,10698,0,10696,10694,10692,10690,10688,10686,10684,10682,10680,10678,10676,10674,10672,10670,10668,0,10666,10664,10662,10660,10658,10656,10654,10652,10650,10648,10646,10644,10642,10640,10638,0,10636,10634,10632,10630,10628,10626,10622,10623,11466,11467,12342,12343,13250,13251,14190,0,14191,15162,15163,16166,16167,17202,17203,18270,18271,19370,19371,
19723,19722,18607,18606,17523,17522,16471,16470,15451,15450,14463,1,14462,13507,13506,12583,12582,11691,11690,10833,10831,10829,10827,10825,10823,10821,10819,1,10817,10815,10813,10811,10809,10807,10805,10803,10801,10799,10797,10795,10793,10791,10789,1,10787,10785,10783,10781,10779,10777,10775,10773,10771,10769,10767,10765,10763,10761,10759,1,10757,10755,10753,10751,10749,10747,10745,10743,10741,10739,10737,10735,10733,10731,10729,1,10727,10725,10723,10721,10719,10717,10715,10713,10711,10709,10707,10705,10703,10701,10699,1,10697,10695,10693,10691,10689,10687,10685,10683,10681,10679,10677,10675,10673,10671,10669,1,10667,10665,10663,10661,10659,10657,10655,10653,10651,10649,10647,10645,10643,10641,10639,1,10637,10635,10633,10631,10629,10627,10624,10625,11468,11469,12344,12345,13252,13253,14192,1,14193,15164,15165,16168,16169,17204,17205,18272,18273,19372,19373,
19721,19720,18605,18604,17521,17520,16469,16468,15449,15448,14461,0,14460,13505,13504,12581,12580,11688,11686,11684,11682,11680,11678,11676,11674,11672,11670,0,11668,11666,11664,11662,11660,11658,11656,11654,11652,11650,11648,11646,11644,11642,11640,0,11638,11636,11634,11632,11630,11628,11626,11624,11622,11620,11618,11616,11614,11612,11610,0,11608,11606,11604,11602,11600,11598,11596,11594,11592,11590,11588,11586,11584,11582,11580,0,11578,11576,11574,11572,11570,11568,11566,11564,11562,11560,11558,11556,11554,11552,11550,0,11548,11546,11544,11542,11540,11538,11536,11534,11532,11530,11528,11526,11524,11522,11520,0,11518,11516,11514,11512,11510,11508,11506,11504,11502,11500,11498,11496,11494,11492,11490,0,11488,11486,11484,11482,11480,11478,11476,11474,11470,11471,12346,12347,13254,13255,14194,0,14195,15166,15167,16170,16171,17206,17207,18274,18275,19374,19375,
19719,19718,18603,18602,17519,17518,16467,16466,15447,15446,14459,1,14458,13503,13502,12579,12578,11689,11687,11685,11683,11681,11679,11677,11675,11673,11671,1,11669,11667,11665,11663,11661,11659,11657,11655,11653,11651,11649,11647,11645,11643,11641,1,11639,11637,11635,11633,11631,11629,11627,11625,11623,11621,11619,11617,11615,11613,11611,1,11609,11607,11605,11603,11601,11599,11597,11595,11593,11591,11589,11587,11585,11583,11581,1,11579,11577,11575,11573,11571,11569,11567,11565,11563,11561,11559,11557,11555,11553,11551,1,11549,11547,11545,11543,11541,11539,11537,11535,11533,11531,11529,11527,11525,11523,11521,1,11519,11517,11515,11513,11511,11509,11507,11505,11503,11501,11499,11497,11495,11493,11491,1,11489,11487,11485,11483,11481,11479,11477,11475,11472,11473,12348,12349,13256,13257,14196,1,14197,15168,15169,16172,16173,17208,17209,18276,18277,19376,19377,
19717,19716,18601,18600,17517,17516,16465,16464,15445,15444,14457,0,14456,13501,13500,12576,12574,12572,12570,12568,12566,12564,12562,12560,12558,12556,12554,0,12552,12550,12548,12546,12544,12542,12540,12538,12536,12534,12532,12530,12528,12526,12524,0,12522,12520,12518,12516,12514,12512,12510,12508,12506,12504,12502,12500,12498,12496,12494,0,12492,12490,12488,12486,12484,12482,12480,12478,12476,12474,12472,12470,12468,12466,12464,0,12462,12460,12458,12456,12454,12452,12450,12448,12446,12444,12442,12440,12438,12436,12434,0,12432,12430,12428,12426,12424,12422,12420,12418,12416,12414,12412,12410,12408,12406,12404,0,12402,12400,12398,12396,12394,12392,12390,12388,12386,12384,12382,12380,12378,12376,12374,0,12372,12370,12368,12366,12364,12362,12360,12358,12356,12354,12350,12351,13258,13259,14198,0,14199,15170,15171,16174,16175,17210,17211,18278,18279,19378,19379,
19715,19714,18599,18598,17515,17514,16463,16462,15443,15442,14455,1,14454,13499,13498,12577,12575,12573,12571,12569,12567,12565,12563,12561,12559,12557,12555,1,12553,12551,12549,12547,12545,12543,12541,12539,12537,12535,12533,12531,12529,12527,12525,1,12523,12521,12519,12517,12515,12513,12511,12509,12507,12505,12503,12501,12499,12497,12495,1,12493,12491,12489,12487,12485,12483,12481,12479,12477,12475,12473,12471,12469,12467,12465,1,12463,12461,12459,12457,12455,12453,12451,12449,12447,12445,12443,12441,12439,12437,12435,1,12433,12431,12429,12427,12425,12423,12421,12419,12417,12415,12413,12411,12409,12407,12405,1,12403,12401,12399,12397,12395,12393,12391,12389,12387,12385,12383,12381,12379,12377,12375,1,12373,12371,12369,12367,12365,12363,12361,12359,12357,12355,12352,12353,13260,13261,14200,1,14201,15172,15173,16176,16177,17212,17213,18280,18281,19380,19381,
19713,19712,18597,18596,17513,17512,16461,16460,15441,15440,14453,0,14452,13496,13494,13492,13490,13488,13486,13484,13482,13480,13478,13476,13474,13472,13470,0,13468,13466,13464,13462,13460,13458,13456,13454,13452,13450,13448,13446,13444,13442,13440,0,13438,13436,13434,13432,13430,13428,13426,13424,13422,13420,13418,13416,13414,13412,13410,0,13408,13406,13404,13402,13400,13398,13396,13394,13392,13390,13388,13386,13384,13382,13380,0,13378,13376,13374,13372,13370,13368,13366,13364,13362,13360,13358,13356,13354,13352,13350,0,13348,13346,13344,13342,13340,13338,13336,13334,13332,13330,13328,13326,13324,13322,13320,0,13318,13316,13314,13312,13310,13308,13306,13304,13302,13300,13298,13296,13294,13292,13290,0,13288,13286,13284,13282,13280,13278,13276,13274,13272,13270,13268,13266,13262,13263,14202,0,14203,15174,15175,16178,16179,17214,17215,18282,18283,19382,19383,
19711,19710,18595,18594,17511,17510,16459,16458,15439,15438,14451,1,14450,13497,13495,13493,13491,13489,13487,13485,13483,13481,13479,13477,13475,13473,13471,1,13469,13467,13465,13463,13461,13459,13457,13455,13453,13451,13449,13447,13445,13443,13441,1,13439,13437,13435,13433,13431,13429,13427,13425,13423,13421,13419,13417,13415,13413,13411,1,13409,13407,13405,13403,13401,13399,13397,13395,13393,13391,13389,13387,13385,13383,13381,1,13379,13377,13375,13373,13371,13369,13367,13365,13363,13361,13359,13357,13355,13353,13351,1,13349,13347,13345,13343,13341,13339,13337,13335,13333,13331,13329,13327,13325,13323,13321,1,13319,13317,13315,13313,13311,13309,13307,13305,13303,13301,13299,13297,13295,13293,13291,1,13289,13287,13285,13283,13281,13279,13277,13275,13273,13271,13269,13267,13264,13265,14204,1,14205,15176,15177,16180,16181,17216,17217,18284,18285,19384,19385,
19709,19708,18593,18592,17509,17508,16457,16456,15437,15436,14448,0,14446,14444,14442,14440,14438,14436,14434,14432,14430,14428,14426,14424,14422,14420,14418,0,14416,14414,14412,14410,14408,14406,14404,14402,14400,14398,14396,14394,14392,14390,14388,0,14386,14384,14382,14380,14378,14376,14374,14372,14370,14368,14366,14364,14362,14360,14358,0,14356,14354,14352,14350,14348,14346,14344,14342,14340,14338,14336,14334,14332,14330,14328,0,14326,14324,14322,14320,14318,14316,14314,14312,14310,14308,14306,14304,14302,14300,14298,0,14296,14294,14292,14290,14288,14286,14284,14282,14280,14278,14276,14274,14272,14270,14268,0,14266,14264,14262,14260,14258,14256,14254,14252,14250,14248,14246,14244,14242,14240,14238,0,14236,14234,14232,14230,14228,14226,14224,14222,14220,14218,14216,14214,14212,14210,14206,0,14207,15178,15179,16182,16183,17218,17219,18286,18287,19386,19387,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,
19707,19706,18591,18590,17507,17506,16455,16454,15435,15434,14449,0,14447,14445,14443,14441,14439,14437,14435,14433,14431,14429,14427,14425,14423,14421,14419,0,14417,14415,14413,14411,14409,14407,14405,14403,14401,14399,14397,14395,14393,14391,14389,0,14387,14385,14383,14381,14379,14377,14375,14373,14371,14369,14367,14365,14363,14361,14359,0,14357,14355,14353,14351,14349,14347,14345,14343,14341,14339,14337,14335,14333,14331,14329,0,14327,14325,14323,14321,14319,14317,14315,14313,14311,14309,14307,14305,14303,14301,14299,0,14297,14295,14293,14291,14289,14287,14285,14283,14281,14279,14277,14275,14273,14271,14269,0,14267,14265,14263,14261,14259,14257,14255,14253,14251,14249,14247,14245,14243,14241,14239,0,14237,14235,14233,14231,14229,14227,14225,14223,14221,14219,14217,14215,14213,14211,14208,0,14209,15180,15181,16184,16185,17220,17221,18288,18289,19388,19389,
19705,19704,18589,18588,17505,17504,16453,16452,15432,15430,15428,1,15426,15424,15422,15420,15418,15416,15414,15412,15410,15408,15406,15404,15402,15400,15398,1,15396,15394,15392,15390,15388,15386,15384,15382,15380,15378,15376,15374,15372,15370,15368,1,15366,15364,15362,15360,15358,15356,15354,15352,15350,15348,15346,15344,15342,15340,15338,1,15336,15334,15332,15330,15328,15326,15324,15322,15320,15318,15316,15314,15312,15310,15308,1,15306,15304,15302,15300,15298,15296,15294,15292,15290,15288,15286,15284,15282,15280,15278,1,15276,15274,15272,15270,15268,15266,15264,15262,15260,15258,15256,15254,15252,15250,15248,1,15246,15244,15242,15240,15238,15236,15234,15232,15230,15228,15226,15224,15222,15220,15218,1,15216,15214,15212,15210,15208,15206,15204,15202,15200,15198,15196,15194,15192,15190,15188,1,15186,15182,15183,16186,16187,17222,17223,18290,18291,19390,19391,
19703,19702,18587,18586,17503,17502,16451,16450,15433,15431,15429,0,15427,15425,15423,15421,15419,15417,15415,15413,15411,15409,15407,15405,15403,15401,15399,0,15397,15395,15393,15391,15389,15387,15385,15383,15381,15379,15377,15375,15373,15371,15369,0,15367,15365,15363,15361,15359,15357,15355,15353,15351,15349,15347,15345,15343,15341,15339,0,15337,15335,15333,15331,15329,15327,15325,15323,15321,15319,15317,15315,15313,15311,15309,0,15307,15305,15303,15301,15299,15297,15295,15293,15291,15289,15287,15285,15283,15281,15279,0,15277,15275,15273,15271,15269,15267,15265,15263,15261,15259,15257,15255,15253,15251,15249,0,15247,15245,15243,15241,15239,15237,15235,15233,15231,15229,15227,15225,15223,15221,15219,0,15217,15215,15213,15211,15209,15207,15205,15203,15201,15199,15197,15195,15193,15191,15189,0,15187,15184,15185,16188,16189,17224,17225,18292,18293,19392,19393,
19701,19700,18585,18584,17501,17500,16448,16446,16444,16442,16440,1,16438,16436,16434,16432,16430,16428,16426,16424,16422,16420,16418,16416,16414,16412,16410,1,16408,16406,16404,16402,16400,16398,16396,16394,16392,16390,16388,16386,16384,16382,16380,1,16378,16376,16374,16372,16370,16368,16366,16364,16362,16360,16358,16356,16354,16352,16350,1,16348,16346,16344,16342,16340,16338,16336,16334,16332,16330,16328,16326,16324,16322,16320,1,16318,16316,16314,16312,16310,16308,16306,16304,16302,16300,16298,16296,16294,16292,16290,1,16288,16286,16284,16282,16280,16278,16276,16274,16272,16270,16268,16266,16264,16262,16260,1,16258,16256,16254,16252,16250,16248,16246,16244,16242,16240,16238,16236,16234,16232,16230,1,16228,16226,16224,16222,16220,16218,16216,16214,16212,16210,16208,16206,16204,16202,16200,1,16198,16196,16194,16190,16191,17226,17227,18294,18295,19394,19395,
19699,19698,18583,18582,17499,17498,16449,16447,16445,16443,16441,0,16439,16437,16435,16433,16431,16429,16427,16425,16423,16421,16419,16417,16415,16413,16411,0,16409,16407,16405,16403,16401,16399,16397,16395,16393,16391,16389,16387,16385,16383,16381,0,16379,16377,16375,16373,16371,16369,16367,16365,16363,16361,16359,16357,16355,16353,16351,0,16349,16347,16345,16343,16341,16339,16337,16335,16333,16331,16329,16327,16325,16323,16321,0,16319,16317,16315,16313,16311,16309,16307,16305,16303,16301,16299,16297,16295,16293,16291,0,16289,16287,16285,16283,16281,16279,16277,16275,16273,16271,16269,16267,16265,16263,16261,0,16259,16257,16255,16253,16251,16249,16247,16245,16243,16241,16239,16237,16235,16233,16231,0,16229,16227,16225,16223,16221,16219,16217,16215,16213,16211,16209,16207,16205,16203,16201,0,16199,16197,16195,16192,16193,17228,17229,18296,18297,19396,19397,
19697,19696,18581,18580,17496,17494,17492,17490,17488,17486,17484,1,17482,17480,17478,17476,17474,17472,17470,17468,17466,17464,17462,17460,17458,17456,17454,1,17452,17450,17448,17446,17444,17442,17440,17438,17436,17434,17432,17430,17428,17426,17424,1,17422,17420,17418,17416,17414,17412,17410,17408,17406,17404,17402,17400,17398,17396,17394,1,17392,17390,17388,17386,17384,17382,17380,17378,17376,17374,17372,17370,17368,17366,17364,1,17362,17360,17358,17356,17354,17352,17350,17348,17346,17344,17342,17340,17338,17336,17334,1,17332,17330,17328,17326,17324,17322,17320,17318,17316,17314,17312,17310,17308,17306,17304,1,17302,17300,17298,17296,17294,17292,17290,17288,17286,17284,17282,17280,17278,17276,17274,1,17272,17270,17268,17266,17264,17262,17260,17258,17256,17254,17252,17250,17248,17246,17244,1,17242,17240,17238,17236,17234,17230,17231,18298,18299,19398,19399,
19695,19694,18579,18578,17497,17495,17493,17491,17489,17487,17485,0,17483,17481,17479,17477,17475,17473,17471,17469,17467,17465,17463,17461,17459,17457,17455,0,17453,17451,17449,17447,17445,17443,17441,17439,17437,17435,17433,17431,17429,17427,17425,0,17423,17421,17419,17417,17415,17413,17411,17409,17407,17405,17403,17401,17399,17397,17395,0,17393,17391,17389,17387,17385,17383,17381,17379,17377,17375,17373,17371,17369,17367,17365,0,17363,17361,17359,17357,17355,17353,17351,17349,17347,17345,17343,17341,17339,17337,17335,0,17333,17331,17329,17327,17325,17323,17321,17319,17317,17315,17313,17311,17309,17307,17305,0,17303,17301,17299,17297,17295,17293,17291,17289,17287,17285,17283,17281,17279,17277,17275,0,17273,17271,17269,17267,17265,17263,17261,17259,17257,17255,17253,17251,17249,17247,17245,0,17243,17241,17239,17237,17235,17232,17233,18300,18301,19400,19401,
19693,19692,18576,18574,18572,18570,18568,18566,18564,18562,18560,1,18558,18556,18554,18552,18550,18548,18546,18544,18542,18540,18538,18536,18534,18532,18530,1,18528,18526,18524,18522,18520,18518,18516,18514,18512,18510,18508,18506,18504,18502,18500,1,18498,18496,18494,18492,18490,18488,18486,18484,18482,18480,18478,18476,18474,18472,18470,1,18468,18466,18464,18462,18460,18458,18456,18454,18452,18450,18448,18446,18444,18442,18440,1,18438,18436,18434,18432,18430,18428,18426,18424,18422,18420,18418,18416,18414,18412,18410,1,18408,18406,18404,18402,18400,18398,18396,18394,18392,18390,18388,18386,18384,18382,18380,1,18378,18376,18374,18372,18370,18368,18366,18364,18362,18360,18358,18356,18354,18352,18350,1,18348,18346,18344,18342,18340,18338,18336,18334,18332,18330,18328,18326,18324,18322,18320,1,18318,18316,18314,18312,18310,18308,18306,18302,18303,19402,19403,
19691,19690,18577,18575,18573,18571,18569,18567,18565,18563,18561,0,18559,18557,18555,18553,18551,18549,18547,18545,18543,18541,18539,18537,18535,18533,18531,0,18529,18527,18525,18523,18521,18519,18517,18515,18513,18511,18509,18507,18505,18503,18501,0,18499,18497,18495,18493,18491,18489,18487,18485,18483,18481,18479,18477,18475,18473,18471,0,18469,18467,18465,18463,18461,18459,18457,18455,18453,18451,18449,18447,18445,18443,18441,0,18439,18437,18435,18433,18431,18429,18427,18425,18423,18421,18419,18417,18415,18413,18411,0,18409,18407,18405,18403,18401,18399,18397,18395,18393,18391,18389,18387,18385,18383,18381,0,18379,18377,18375,18373,18371,18369,18367,18365,18363,18361,18359,18357,18355,18353,18351,0,18349,18347,18345,18343,18341,18339,18337,18335,18333,18331,18329,18327,18325,18323,18321,0,18319,18317,18315,18313,18311,18309,18307,18304,18305,19404,19405,
19688,19686,19684,19682,19680,19678,19676,19674,19672,19670,19668,1,19666,19664,19662,19660,19658,19656,19654,19652,19650,19648,19646,19644,19642,19640,19638,1,19636,19634,19632,19630,19628,19626,19624,19622,19620,19618,19616,19614,19612,19610,19608,1,19606,19604,19602,19600,19598,19596,19594,19592,19590,19588,19586,19584,19582,19580,19578,1,19576,19574,19572,19570,19568,19566,19564,19562,19560,19558,19556,19554,19552,19550,19548,1,19546,19544,19542,19540,19538,19536,19534,19532,19530,19528,19526,19524,19522,19520,19518,1,19516,19514,19512,19510,19508,19506,19504,19502,19500,19498,19496,19494,19492,19490,19488,1,19486,19484,19482,19480,19478,19476,19474,19472,19470,19468,19466,19464,19462,19460,19458,1,19456,19454,19452,19450,19448,19446,19444,19442,19440,19438,19436,19434,19432,19430,19428,1,19426,19424,19422,19420,19418,19416,19414,19412,19410,19406,19407,
19689,19687,19685,19683,19681,19679,19677,19675,19673,19671,19669,0,19667,19665,19663,19661,19659,19657,19655,19653,19651,19649,19647,19645,19643,19641,19639,0,19637,19635,19633,19631,19629,19627,19625,19623,19621,19619,19617,19615,19613,19611,19609,0,19607,19605,19603,19601,19599,19597,19595,19593,19591,19589,19587,19585,19583,19581,19579,0,19577,19575,19573,19571,19569,19567,19565,19563,19561,19559,19557,19555,19553,19551,19549,0,19547,19545,19543,19541,19539,19537,19535,19533,19531,19529,19527,19525,19523,19521,19519,0,19517,19515,19513,19511,19509,19507,19505,19503,19501,19499,19497,19495,19493,19491,19489,0,19487,19485,19483,19481,19479,19477,19475,19473,19471,19469,19467,19465,19463,19461,19459,0,19457,19455,19453,19451,19449,19447,19445,19443,19441,19439,19437,19435,19433,19431,19429,0,19427,19425,19423,19421,19419,19417,19415,19413,19411,19408,19409
};
static int CompactAztecMap[] = { /* 27 x 27 data grid */
609,608,411,413,415,417,419,421,423,425,427,429,431,433,435,437,439,441,443,445,447,449,451,453,455,457,459,
607,606,410,412,414,416,418,420,422,424,426,428,430,432,434,436,438,440,442,444,446,448,450,452,454,456,458,
605,604,409,408,243,245,247,249,251,253,255,257,259,261,263,265,267,269,271,273,275,277,279,281,283,460,461,
603,602,407,406,242,244,246,248,250,252,254,256,258,260,262,264,266,268,270,272,274,276,278,280,282,462,463,
601,600,405,404,241,240,107,109,111,113,115,117,119,121,123,125,127,129,131,133,135,137,139,284,285,464,465,
599,598,403,402,239,238,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,286,287,466,467,
597,596,401,400,237,236,105,104,3,5,7,9,11,13,15,17,19,21,23,25,27,140,141,288,289,468,469,
595,594,399,398,235,234,103,102,2,4,6,8,10,12,14,16,18,20,22,24,26,142,143,290,291,470,471,
593,592,397,396,233,232,101,100,1,1,2000,2001,2002,2003,2004,2005,2006,0,1,28,29,144,145,292,293,472,473,
591,590,395,394,231,230,99,98,1,1,1,1,1,1,1,1,1,1,1,30,31,146,147,294,295,474,475,
589,588,393,392,229,228,97,96,2027,1,0,0,0,0,0,0,0,1,2007,32,33,148,149,296,297,476,477,
587,586,391,390,227,226,95,94,2026,1,0,1,1,1,1,1,0,1,2008,34,35,150,151,298,299,478,479,
585,584,389,388,225,224,93,92,2025,1,0,1,0,0,0,1,0,1,2009,36,37,152,153,300,301,480,481,
583,582,387,386,223,222,91,90,2024,1,0,1,0,1,0,1,0,1,2010,38,39,154,155,302,303,482,483,
581,580,385,384,221,220,89,88,2023,1,0,1,0,0,0,1,0,1,2011,40,41,156,157,304,305,484,485,
579,578,383,382,219,218,87,86,2022,1,0,1,1,1,1,1,0,1,2012,42,43,158,159,306,307,486,487,
577,576,381,380,217,216,85,84,2021,1,0,0,0,0,0,0,0,1,2013,44,45,160,161,308,309,488,489,
575,574,379,378,215,214,83,82,0,1,1,1,1,1,1,1,1,1,1,46,47,162,163,310,311,490,491,
573,572,377,376,213,212,81,80,0,0,2020,2019,2018,2017,2016,2015,2014,0,0,48,49,164,165,312,313,492,493,
571,570,375,374,211,210,78,76,74,72,70,68,66,64,62,60,58,56,54,50,51,166,167,314,315,494,495,
569,568,373,372,209,208,79,77,75,73,71,69,67,65,63,61,59,57,55,52,53,168,169,316,317,496,497,
567,566,371,370,206,204,202,200,198,196,194,192,190,188,186,184,182,180,178,176,174,170,171,318,319,498,499,
565,564,369,368,207,205,203,201,199,197,195,193,191,189,187,185,183,181,179,177,175,172,173,320,321,500,501,
563,562,366,364,362,360,358,356,354,352,350,348,346,344,342,340,338,336,334,332,330,328,326,322,323,502,503,
561,560,367,365,363,361,359,357,355,353,351,349,347,345,343,341,339,337,335,333,331,329,327,324,325,504,505,
558,556,554,552,550,548,546,544,542,540,538,536,534,532,530,528,526,524,522,520,518,516,514,512,510,506,507,
559,557,555,553,551,549,547,545,543,541,539,537,535,533,531,529,527,525,523,521,519,517,515,513,511,508,509
};
int AztecCodeSet[128] = { /* From Table 2 */
32, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 12, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 4, 4, 4, 4, 4, 23, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 24, 8, 24, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 8,
8, 8, 8, 8, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 4, 8, 4, 4, 4, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 8, 4, 8, 4, 4
};
int AztecSymbolChar[128] = { /* From Table 2 */
0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 300, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 15, 16, 17, 18, 19, 1, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 301, 18, 302, 20, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 21, 22,
23, 24, 25, 26, 20, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 27, 21, 28, 22, 23, 24, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 29, 25, 30, 26, 27
};
/* Problem characters are:
300: Carriage Return (ASCII 13)
301: Comma (ASCII 44)
302: Full Stop (ASCII 46)
*/
static char *hexbit[32] = {"00000", "00001", "00010", "00011", "00100", "00101", "00110", "00111", "01000", "01001",
"01010", "01011", "01100", "01101", "01110", "01111", "10000", "10001", "10010", "10011", "10100", "10101",
"10110", "10111", "11000", "11001", "11010", "11011", "11100", "11101", "11110", "11111"
};
static char *pentbit[16] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001",
"1010", "1011", "1100", "1101", "1110", "1111"
};
static char *tribit[8] = {"000", "001", "010", "011", "100", "101", "110", "111"};
static int AztecSizes[32] = { /* Codewords per symbol */
21, 48, 60, 88, 120, 156, 196, 240, 230, 272, 316, 364, 416, 470, 528, 588, 652, 720, 790,
864, 940, 1020, 920, 992, 1066, 1144, 1224, 1306, 1392, 1480, 1570, 1664
};
static int AztecCompactSizes[4] = { 17, 40, 51, 76 };
static int Aztec10DataSizes[32] = { /* Data bits per symbol maximum with 10% error correction */
96, 246, 408, 616, 840, 1104, 1392, 1704, 2040, 2420, 2820, 3250, 3720, 4200, 4730,
5270, 5840, 6450, 7080, 7750, 8430, 9150, 9900, 10680, 11484, 12324, 13188, 14076,
15000, 15948, 16920, 17940
};
static int Aztec23DataSizes[32] = { /* Data bits per symbol maximum with 23% error correction */
84, 204, 352, 520, 720, 944, 1184, 1456, 1750, 2070, 2410, 2780, 3180, 3590, 4040,
4500, 5000, 5520, 6060, 6630, 7210, 7830, 8472, 9132, 9816, 10536, 11280, 12036,
12828, 13644, 14472, 15348
};
static int Aztec36DataSizes[32] = { /* Data bits per symbol maximum with 36% error correction */
66, 168, 288, 432, 592, 776, 984, 1208, 1450, 1720, 2000, 2300, 2640, 2980, 3350,
3740, 4150, 4580, 5030, 5500, 5990, 6500, 7032, 7584, 8160, 8760, 9372, 9996, 10656,
11340, 12024, 12744
};
static int Aztec50DataSizes[32] = { /* Data bits per symbol maximum with 50% error correction */
48, 126, 216, 328, 456, 600, 760, 936, 1120, 1330, 1550, 1790, 2050, 2320, 2610,
2910, 3230, 3570, 3920, 4290, 4670, 5070, 5484, 5916, 6360, 6828, 7308, 7800, 8316,
8844, 9384, 9948
};
static int AztecCompact10DataSizes [4] = { 78, 198, 336, 520 };
static int AztecCompact23DataSizes [4] = { 66, 168, 288, 440 };
static int AztecCompact36DataSizes [4] = { 48, 138, 232, 360 };
static int AztecCompact50DataSizes [4] = { 36, 102, 176, 280 };
static int AztecOffset[32] = {
66, 64, 62, 60, 57, 55, 53, 51, 49, 47, 45, 42, 40, 38, 36, 34, 32, 30, 28, 25, 23, 21,
19, 17, 15, 13, 10, 8, 6, 4, 2, 0
};
static int AztecCompactOffset[4] = { 6, 4, 2, 0 };

542
backend/code.c Normal file
View file

@ -0,0 +1,542 @@
/* code.c - Handles Code 11, 39, 39+ and 93 */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* In version 0.5 this file was 1,553 lines long! */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#define SODIUM "0123456789-"
#define SILVER "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd"
static char *C11Table[11] = {"111121", "211121", "121121", "221111", "112121", "212111", "122111",
"111221", "211211", "211111", "112111"};
/* Code 39 tables checked against ISO/IEC 16388:2007 */
/* Incorporates Table A1 */
static char *C39Table[43] = { "1112212111", "2112111121", "1122111121", "2122111111", "1112211121",
"2112211111", "1122211111", "1112112121", "2112112111", "1122112111", "2111121121",
"1121121121", "2121121111", "1111221121", "2111221111", "1121221111", "1111122121",
"2111122111", "1121122111", "1111222111", "2111111221", "1121111221", "2121111211",
"1111211221", "2111211211", "1121211211", "1111112221", "2111112211", "1121112211",
"1111212211", "2211111121", "1221111121", "2221111111", "1211211121", "2211211111",
"1221211111", "1211112121", "2211112111", "1221112111", "1212121111", "1212111211",
"1211121211", "1112121211"};
/* Code 39 character assignments (Table 1) */
static char *EC39Ctrl[128] = {"%U", "$A", "$B", "$C", "$D", "$E", "$F", "$G", "$H", "$I", "$J", "$K",
"$L", "$M", "$N", "$O", "$P", "$Q", "$R", "$S", "$T", "$U", "$V", "$W", "$X", "$Y", "$Z",
"%A", "%B", "%C", "%D", "%E", " ", "/A", "/B", "/C", "/D", "/E", "/F", "/G", "/H", "/I", "/J",
"/K", "/L", "-", ".", "/O", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "/Z", "%F",
"%G", "%H", "%I", "%J", "%V", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "%K", "%L", "%M", "%N", "%O",
"%W", "+A", "+B", "+C", "+D", "+E", "+F", "+G", "+H", "+I", "+J", "+K", "+L", "+M", "+N", "+O",
"+P", "+Q", "+R", "+S", "+T", "+U", "+V", "+W", "+X", "+Y", "+Z", "%P", "%Q", "%R", "%S", "%T"};
/* Encoding the full ASCII character set in Code 39 (Table A2) */
static char *C93Ctrl[128] = {"bU", "aA", "aB", "aC", "aD", "aE", "aF", "aG", "aH", "aI", "aJ", "aK",
"aL", "aM", "aN", "aO", "aP", "aQ", "aR", "aS", "aT", "aU", "aV", "aW", "aX", "aY", "aZ",
"bA", "bB", "bC", "bD", "bE", " ", "cA", "cB", "cC", "cD", "cE", "cF", "cG", "cH", "cI", "cJ",
"cK", "cL", "cM", "cN", "cO", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "cZ", "bF",
"bG", "bH", "bI", "bJ", "bV", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bK", "bL", "bM", "bN", "bO",
"bW", "dA", "dB", "dC", "dD", "dE", "dF", "dG", "dH", "dI", "dJ", "dK", "dL", "dM", "dN", "dO",
"dP", "dQ", "dR", "dS", "dT", "dU", "dV", "dW", "dX", "dY", "dZ", "bP", "bQ", "bR", "bS", "bT"};
static char *C93Table[47] = {"131112", "111213", "111312", "111411", "121113", "121212", "121311",
"111114", "131211", "141111", "211113", "211212", "211311", "221112", "221211", "231111",
"112113", "112212", "112311", "122112", "132111", "111123", "111222", "111321", "121122",
"131121", "212112", "212211", "211122", "211221", "221121", "222111", "112122", "112221",
"122121", "123111", "121131", "311112", "311211", "321111", "112131", "113121", "211131",
"121221", "312111", "311121", "122211"};
/* Global Variables for Channel Code */
int S[11], B[11];
long value;
long target_value;
char pattern[30];
/* Function Prototypes */
void NextS(int Chan, int i, int MaxS, int MaxB);
void NextB(int Chan, int i, int MaxB, int MaxS);
/* *********************** CODE 11 ******************** */
int code_11(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Code 11 */
unsigned int i;
int h, c_digit, c_weight, c_count, k_digit, k_weight, k_count;
int weight[128], error_number;
char dest[1024]; /* 6 + 121 * 6 + 2 * 6 + 5 + 1 ~ 1024*/
char checkstr[3];
error_number = 0;
if(length > 121) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(SODIUM, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
c_weight = 1;
c_count = 0;
k_weight = 1;
k_count = 0;
/* start character */
strcpy(dest, "112211");
/* Draw main body of barcode */
for(i = 0; i < length; i++) {
lookup(SODIUM, C11Table, source[i], dest);
if(source[i] == '-')
weight[i] = 10;
else
weight[i] = ctoi(source[i]);
}
/* Calculate C checksum */
for(h = length - 1; h >= 0; h--) {
c_count += (c_weight * weight[h]);
c_weight++;
if(c_weight > 10) {
c_weight = 1;
}
}
c_digit = c_count % 11;
weight[length] = c_digit;
/* Calculate K checksum */
for(h = length; h >= 0; h--) {
k_count += (k_weight * weight[h]);
k_weight++;
if(k_weight > 9) {
k_weight = 1;
}
}
k_digit = k_count % 11;
checkstr[0] = itoc(c_digit);
checkstr[1] = itoc(k_digit);
if(checkstr[0] == 'A') { checkstr[0] = '-'; }
if(checkstr[1] == 'A') { checkstr[1] = '-'; }
checkstr[2] = '\0';
lookup(SODIUM, C11Table, checkstr[0], dest);
lookup(SODIUM, C11Table, checkstr[1], dest);
/* Stop character */
concat (dest, "11221");
expand(symbol, dest);
ustrcpy(symbol->text, source);
uconcat(symbol->text, (unsigned char*)checkstr);
return error_number;
}
int c39(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Code 39 */
unsigned int i;
unsigned int counter;
char check_digit;
int error_number;
char dest[775];
char localstr[2] = { 0 };
error_number = 0;
counter = 0;
if((symbol->option_2 < 0) || (symbol->option_2 > 1)) {
symbol->option_2 = 0;
}
if((symbol->symbology == BARCODE_LOGMARS) && (length > 59)) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
} else if(length > 74) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
to_upper(source);
error_number = is_sane(SILVER , source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
/* Start character */
strcpy(dest, "1211212111");
for(i = 0; i < length; i++) {
lookup(SILVER, C39Table, source[i], dest);
counter += posn(SILVER, source[i]);
}
if((symbol->symbology == BARCODE_LOGMARS) || (symbol->option_2 == 1)) {
counter = counter % 43;
if(counter < 10) {
check_digit = itoc(counter);
} else {
if(counter < 36) {
check_digit = (counter - 10) + 'A';
} else {
switch(counter) {
case 36: check_digit = '-'; break;
case 37: check_digit = '.'; break;
case 38: check_digit = ' '; break;
case 39: check_digit = '$'; break;
case 40: check_digit = '/'; break;
case 41: check_digit = '+'; break;
case 42: check_digit = 37; break;
default: check_digit = ' '; break; /* Keep compiler happy */
}
}
}
lookup(SILVER, C39Table, check_digit, dest);
/* Display a space check digit as _, otherwise it looks like an error */
if(check_digit == ' ') {
check_digit = '_';
}
localstr[0] = check_digit;
localstr[1] = '\0';
}
/* Stop character */
concat (dest, "121121211");
if((symbol->symbology == BARCODE_LOGMARS) || (symbol->symbology == BARCODE_HIBC_39)) {
/* LOGMARS uses wider 'wide' bars than normal Code 39 */
counter = strlen(dest);
for(i = 0; i < counter; i++) {
if(dest[i] == '2') {
dest[i] = '3';
}
}
}
expand(symbol, dest);
if(symbol->symbology == BARCODE_CODE39) {
ustrcpy(symbol->text, (unsigned char*)"*");
uconcat(symbol->text, source);
uconcat(symbol->text, (unsigned char*)localstr);
uconcat(symbol->text, (unsigned char*)"*");
} else {
ustrcpy(symbol->text, source);
uconcat(symbol->text, (unsigned char*)localstr);
}
return error_number;
}
int pharmazentral(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Pharmazentral Nummer (PZN) */
int i, error_number, zeroes;
unsigned int count, check_digit;
char localstr[10];
error_number = 0;
count = 0;
if(length > 6) {
strcpy(symbol->errtxt, "Input wrong length");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
localstr[0] = '-';
zeroes = 6 - length + 1;
for(i = 1; i < zeroes; i++)
localstr[i] = '0';
strcpy(localstr + zeroes, (char *)source);
for (i = 1; i < 7; i++) {
count += (i + 1) * ctoi(localstr[i]);
}
check_digit = count%11;
if (check_digit == 11) { check_digit = 0; }
localstr[7] = itoc(check_digit);
localstr[8] = '\0';
if(localstr[7] == 'A') {
strcpy(symbol->errtxt, "Invalid PZN Data");
return ERROR_INVALID_DATA;
}
error_number = c39(symbol, (unsigned char *)localstr, strlen(localstr));
ustrcpy(symbol->text, (unsigned char *)"PZN");
uconcat(symbol->text, (unsigned char *)localstr);
return error_number;
}
/* ************** EXTENDED CODE 39 *************** */
int ec39(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Extended Code 39 - ISO/IEC 16388:2007 Annex A */
unsigned char buffer[150] = { 0 };
unsigned int i;
int error_number;
error_number = 0;
if(length > 74) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
/* Creates a buffer string and places control characters into it */
for(i = 0; i < length; i++) {
if(source[i] > 127) {
/* Cannot encode extended ASCII */
strcpy(symbol->errtxt, "Invalid characters in input data");
return ERROR_INVALID_DATA;
}
concat((char*)buffer, EC39Ctrl[source[i]]);
}
/* Then sends the buffer to the C39 function */
error_number = c39(symbol, buffer, ustrlen(buffer));
for(i = 0; i < length; i++)
symbol->text[i] = source[i] ? source[i] : ' ';
symbol->text[length] = '\0';
return error_number;
}
/* ******************** CODE 93 ******************* */
int c93(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Code 93 is an advancement on Code 39 and the definition is a lot tighter */
/* SILVER includes the extra characters a, b, c and d to represent Code 93 specific
shift characters 1, 2, 3 and 4 respectively. These characters are never used by
c39() and ec39() */
int i;
int h, weight, c, k, values[128], error_number;
char buffer[220];
char dest[670];
char set_copy[] = SILVER;
error_number = 0;
strcpy(buffer, "");
if(length > 107) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
/* Message Content */
for (i = 0; i < length; i++) {
if (source[i] > 127) {
/* Cannot encode extended ASCII */
strcpy(symbol->errtxt, "Invalid characters in input data");
return ERROR_INVALID_DATA;
}
concat(buffer, C93Ctrl[source[i]]);
symbol->text[i] = source[i] ? source[i] : ' ';
}
/* Now we can check the true length of the barcode */
h = strlen(buffer);
if (h > 107) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
for (i = 0; i < h; i++) {
values[i] = posn(SILVER, buffer[i]);
}
/* Putting the data into dest[] is not done until after check digits are calculated */
/* Check digit C */
c = 0;
weight = 1;
for (i = h - 1; i >= 0; i--) {
c += values[i] * weight;
weight++;
if (weight == 21)
weight = 1;
}
c = c % 47;
values[h] = c;
buffer[h] = set_copy[c];
/* Check digit K */
k = 0;
weight = 1;
for (i = h; i >= 0; i--) {
k += values[i] * weight;
weight++;
if(weight == 16)
weight = 1;
}
k = k % 47;
buffer[++h] = set_copy[k];
buffer[++h] = '\0';
/* Start character */
strcpy(dest, "111141");
for(i = 0; i < h; i++) {
lookup(SILVER, C93Table, buffer[i], dest);
}
/* Stop character */
concat(dest, "1111411");
expand(symbol, dest);
symbol->text[length] = set_copy[c];
symbol->text[length + 1] = set_copy[k];
symbol->text[length + 2] = '\0';
return error_number;
}
/* NextS() and NextB() are from ANSI/AIM BC12-1998 and are Copyright (c) AIM 1997 */
/* Their are used here on the understanding that they form part of the specification
for Channel Code and therefore their use is permitted under the following terms
set out in that document:
"It is the intent and understanding of AIM [t]hat the symbology presented in this
specification is entirely in the public domain and free of all use restrictions,
licenses and fees. AIM USA, its memer companies, or individual officers
assume no liability for the use of this document." */
void CheckCharacter() {
int i;
char part[3];
if(value == target_value) {
/* Target reached - save the generated pattern */
strcpy(pattern, "11110");
for(i = 0; i < 11; i++) {
part[0] = itoc(S[i]);
part[1] = itoc(B[i]);
part[2] = '\0';
concat(pattern, part);
}
}
}
void NextB(int Chan, int i, int MaxB, int MaxS) {
int b;
b = (S[i]+B[i-1]+S[i-1]+B[i-2] > 4)? 1:2;
if (i < Chan+2) {
for (; b <= MaxB; b++) {
B[i] = b;
NextS(Chan,i+1,MaxS,MaxB+1-b);
}
} else if (b <= MaxB) {
B[i] = MaxB;
CheckCharacter();
value++;
}
}
void NextS(int Chan, int i, int MaxS, int MaxB) {
int s;
for (s = (i<Chan+2)? 1: MaxS; s <= MaxS; s++) {
S[i] = s;
NextB(Chan,i,MaxB,MaxS+1-s);
}
}
int channel_code(struct zint_symbol *symbol, unsigned char source[], int length) {
/* Channel Code - According to ANSI/AIM BC12-1998 */
int channels, i;
int error_number = 0, range = 0, zeroes;
char hrt[9];
target_value = 0;
if(length > 7) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
if((symbol->option_2 < 3) || (symbol->option_2 > 8)) { channels = 0; } else { channels = symbol->option_2; }
if(channels == 0) { channels = length + 1; }
if(channels == 2) { channels = 3; }
for(i = 0; i < length; i++) {
target_value *= 10;
target_value += ctoi((char) source[i]);
}
switch(channels) {
case 3: if(target_value > 26) { range = 1; } break;
case 4: if(target_value > 292) { range = 1; } break;
case 5: if(target_value > 3493) { range = 1; } break;
case 6: if(target_value > 44072) { range = 1; } break;
case 7: if(target_value > 576688) { range = 1; } break;
case 8: if(target_value > 7742862) { range = 1; } break;
}
if(range) {
strcpy(symbol->errtxt, "Value out of range");
return ERROR_INVALID_DATA;
}
for(i = 0; i < 11; i++) { B[i] = 0; S[i] = 0; }
B[0] = S[1] = B[1] = S[2] = B[2] = 1;
value = 0;
NextS(channels,3,channels,channels);
zeroes = channels - 1 - length;
memset(hrt, '0', zeroes);
strcpy(hrt + zeroes, (char *)source);
ustrcpy(symbol->text, (unsigned char *)hrt);
expand(symbol, pattern);
return error_number;
}

1536
backend/code1.c Normal file

File diff suppressed because it is too large Load diff

61
backend/code1.h Normal file
View file

@ -0,0 +1,61 @@
/* code1.h - Lookup info for USS Code One */
/*
libzint - the open source barcode library
Copyright (C) 2009 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
static int c40_shift[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };
static int c40_value[] = {
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
3,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,4,5,6,7,8,9,10,11,12,13,
15,16,17,18,19,20,21,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,
22,23,24,25,26,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 };
static int text_shift[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3 };
static int text_value[] = {
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
3,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,4,5,6,7,8,9,10,11,12,13,
15,16,17,18,19,20,21,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,
22,23,24,25,26,0,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,27,28,29,30,31 };
static int c1_height[] = { 16, 22, 28, 40, 52, 70, 104, 148 };
static int c1_width[] = { 18, 22, 32, 42, 54, 76, 98, 134 };
static int c1_data_length[] = { 10, 19, 44, 91, 182, 370, 732, 1480 };
static int c1_ecc_length[] = { 10, 16, 26, 44, 70, 140, 280, 560 };
static int c1_blocks[] = { 1, 1, 1, 1, 1, 2, 4, 8 };
static int c1_data_blocks[] = { 10, 19, 44, 91, 182, 185, 183, 185 };
static int c1_ecc_blocks[] = { 10, 16, 26, 44, 70, 70, 70, 70 };
static int c1_grid_width[] = { 4, 5, 7, 9, 12, 17, 22, 30 };
static int c1_grid_height[] = { 5, 7, 10, 15, 21, 30, 46, 68 };
#define C1_ASCII 1
#define C1_C40 2
#define C1_DECIMAL 3
#define C1_TEXT 4
#define C1_EDI 5
#define C1_BYTE 6

999
backend/code128.c Normal file
View file

@ -0,0 +1,999 @@
/* code128.c - Handles Code 128 and derivatives */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
Bugfixes thanks to Christian Sakowski and BogDan Vatra
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef _MSC_VER
#include <malloc.h>
#endif
#include "common.h"
#include "gs1.h"
#define TRUE 1
#define FALSE 0
#define SHIFTA 90
#define LATCHA 91
#define SHIFTB 92
#define LATCHB 93
#define SHIFTC 94
#define LATCHC 95
#define AORB 96
#define ABORC 97
#define DPDSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*"
static int list[2][170];
/* Code 128 tables checked against ISO/IEC 15417:2007 */
static char *C128Table[107] = {"212222", "222122", "222221", "121223", "121322", "131222", "122213",
"122312", "132212", "221213", "221312", "231212", "112232", "122132", "122231", "113222",
"123122", "123221", "223211", "221132", "221231", "213212", "223112", "312131", "311222",
"321122", "321221", "312212", "322112", "322211", "212123", "212321", "232121", "111323",
"131123", "131321", "112313", "132113", "132311", "211313", "231113", "231311", "112133",
"112331", "132131", "113123", "113321", "133121", "313121", "211331", "231131", "213113",
"213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111", "314111",
"221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214",
"112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112",
"134111", "111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112",
"421211", "212141", "214121", "412121", "111143", "111341", "131141", "114113", "114311",
"411113", "411311", "113141", "114131", "311141", "411131", "211412", "211214", "211232",
"2331112"};
/* Code 128 character encodation - Table 1 */
int parunmodd(unsigned char llyth)
{
int modd;
modd = 0;
if(llyth <= 31) { modd = SHIFTA; }
else if((llyth >= 48) && (llyth <= 57)) { modd = ABORC; }
else if(llyth <= 95) { modd = AORB; }
else if(llyth <= 127) { modd = SHIFTB; }
else if(llyth <= 159) { modd = SHIFTA; }
else if(llyth <= 223) { modd = AORB; }
else { modd = SHIFTB; }
return modd;
}
void grwp(int *indexliste)
{
int i, j;
/* bring together same type blocks */
if(*(indexliste) > 1) {
i = 1;
while(i < *(indexliste)) {
if(list[1][i - 1] == list[1][i]) {
/* bring together */
list[0][i - 1] = list[0][i - 1] + list[0][i];
j = i + 1;
/* decreace the list */
while(j < *(indexliste)) {
list[0][j - 1] = list[0][j];
list[1][j - 1] = list[1][j];
j++;
}
*(indexliste) = *(indexliste) - 1;
i--;
}
i++;
}
}
}
void dxsmooth(int *indexliste)
{ /* Implements rules from ISO 15417 Annex E */
int i, current, last, next, length;
for(i = 0; i < *(indexliste); i++) {
current = list[1][i];
length = list[0][i];
if(i != 0) { last = list[1][i - 1]; } else { last = FALSE; }
if(i != *(indexliste) - 1) { next = list[1][i + 1]; } else { next = FALSE; }
if(i == 0) { /* first block */
if((*(indexliste) == 1) && ((length == 2) && (current == ABORC))) { /* Rule 1a */ list[1][i] = LATCHC; }
if(current == ABORC) {
if(length >= 4) {/* Rule 1b */ list[1][i] = LATCHC; } else { list[1][i] = AORB; current = AORB; }
}
if(current == SHIFTA) { /* Rule 1c */ list[1][i] = LATCHA; }
if((current == AORB) && (next == SHIFTA)) { /* Rule 1c */ list[1][i] = LATCHA; current = LATCHA; }
if(current == AORB) { /* Rule 1d */ list[1][i] = LATCHB; }
} else {
if((current == ABORC) && (length >= 4)) { /* Rule 3 */ list[1][i] = LATCHC; current = LATCHC; }
if(current == ABORC) { list[1][i] = AORB; current = AORB; }
if((current == AORB) && (last == LATCHA)) { list[1][i] = LATCHA; current = LATCHA; }
if((current == AORB) && (last == LATCHB)) { list[1][i] = LATCHB; current = LATCHB; }
if((current == AORB) && (next == SHIFTA)) { list[1][i] = LATCHA; current = LATCHA; }
if((current == AORB) && (next == SHIFTB)) { list[1][i] = LATCHB; current = LATCHB; }
if(current == AORB) { list[1][i] = LATCHB; current = LATCHB; }
if((current == SHIFTA) && (length > 1)) { /* Rule 4 */ list[1][i] = LATCHA; current = LATCHA; }
if((current == SHIFTB) && (length > 1)) { /* Rule 5 */ list[1][i] = LATCHB; current = LATCHB; }
if((current == SHIFTA) && (last == LATCHA)) { list[1][i] = LATCHA; current = LATCHA; }
if((current == SHIFTB) && (last == LATCHB)) { list[1][i] = LATCHB; current = LATCHB; }
if((current == SHIFTA) && (last == LATCHC)) { list[1][i] = LATCHA; current = LATCHA; }
if((current == SHIFTB) && (last == LATCHC)) { list[1][i] = LATCHB; current = LATCHB; }
} /* Rule 2 is implimented elsewhere, Rule 6 is implied */
}
grwp(indexliste);
}
void c128_set_a(unsigned char source, char dest[], int values[], int *bar_chars)
{ /* Translate Code 128 Set A characters into barcodes */
/* This set handles all control characters NULL to US */
if(source > 127) {
if(source < 160) {
concat(dest, C128Table[(source - 128) + 64]);
values[(*bar_chars)] = (source - 128) + 64;
} else {
concat(dest, C128Table[(source - 128) - 32]);
values[(*bar_chars)] = (source - 128) - 32;
}
} else {
if(source < 32) {
concat(dest, C128Table[source + 64]);
values[(*bar_chars)] = source + 64;
} else {
concat(dest, C128Table[source - 32]);
values[(*bar_chars)] = source - 32;
}
}
(*bar_chars)++;
}
void c128_set_b(unsigned char source, char dest[], int values[], int *bar_chars)
{ /* Translate Code 128 Set B characters into barcodes */
/* This set handles all characters which are not part of long numbers and not control characters */
if(source > 127) {
concat(dest, C128Table[source - 32 - 128]);
values[(*bar_chars)] = source - 32 - 128;
} else {
concat(dest, C128Table[source - 32]);
values[(*bar_chars)] = source - 32;
}
(*bar_chars)++;
}
void c128_set_c(unsigned char source_a, unsigned char source_b, char dest[], int values[], int *bar_chars)
{ /* Translate Code 128 Set C characters into barcodes */
/* This set handles numbers in a compressed form */
int weight;
weight = (10 * ctoi(source_a)) + ctoi(source_b);
concat(dest, C128Table[weight]);
values[(*bar_chars)] = weight;
(*bar_chars)++;
}
int code_128(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Handle Code 128 and NVE-18 */
int i, j, k, e_count, values[170] = { 0 }, bar_characters, read, total_sum, nve_check;
int error_number, indexchaine, indexliste, sourcelen, f_state;
char set[170] = { ' ' }, fset[170] = { ' ' }, mode, last_set, last_fset, current_set = ' ';
float glyph_count;
char dest[1000];
error_number = 0;
strcpy(dest, "");
sourcelen = length;
j = 0;
e_count = 0;
bar_characters = 0;
nve_check = 0;
f_state = 0;
if(sourcelen > 160) {
/* This only blocks rediculously long input - the actual length of the
resulting barcode depends on the type of data, so this is trapped later */
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
/* Detect extended ASCII characters */
for(i = 0; i < sourcelen; i++) {
if(source[i] >= 128)
fset[i] = 'f';
}
fset[i] = '\0';
/* Decide when to latch to extended mode - Annex E note 3 */
j = 0;
for(i = 0; i < sourcelen; i++) {
if(fset[i] == 'f') {
j++;
} else {
j = 0;
}
if(j >= 5) {
for(k = i; k > (i - 5); k--) {
fset[k] = 'F';
}
}
if((j >= 3) && (i == (sourcelen - 1))) {
for(k = i; k > (i - 3); k--) {
fset[k] = 'F';
}
}
}
/* Decide if it is worth reverting to 646 encodation for a few characters as described in 4.3.4.2 (d) */
for(i = 1; i < sourcelen; i++) {
if((fset[i - 1] == 'F') && (fset[i] == ' ')) {
/* Detected a change from 8859-1 to 646 - count how long for */
for(j = 0; (fset[i + j] == ' ') && ((i + j) < sourcelen); j++);
if((j < 5) || ((j < 3) && ((i + j) == (sourcelen - 1)))) {
/* Uses the same figures recommended by Annex E note 3 */
/* Change to shifting back rather than latching back */
for(k = 0; k < j; k++) {
fset[i + k] = 'n';
}
}
}
}
/* Decide on mode using same system as PDF417 and rules of ISO 15417 Annex E */
indexliste = 0;
indexchaine = 0;
mode = parunmodd(source[indexchaine]);
if((symbol->symbology == BARCODE_CODE128B) && (mode == ABORC)) {
mode = AORB;
}
for(i = 0; i < 170; i++) {
list[0][i] = 0;
}
do {
list[1][indexliste] = mode;
while ((list[1][indexliste] == mode) && (indexchaine < sourcelen)) {
list[0][indexliste]++;
indexchaine++;
mode = parunmodd(source[indexchaine]);
if((symbol->symbology == BARCODE_CODE128B) && (mode == ABORC)) {
mode = AORB;
}
}
indexliste++;
} while (indexchaine < sourcelen);
dxsmooth(&indexliste);
/* Resolve odd length LATCHC blocks */
if((list[1][0] == LATCHC) && ((list[0][0] % 2) == 1)) {
/* Rule 2 */
list[0][1]++;
list[0][0]--;
if(indexliste == 1) {
list[0][1] = 1;
list[1][1] = LATCHB;
indexliste = 2;
}
}
if(indexliste > 1) {
for(i = 1; i < indexliste; i++) {
if((list[1][i] == LATCHC) && ((list[0][i] % 2) == 1)) {
/* Rule 3b */
list[0][i - 1]++;
list[0][i]--;
}
}
}
/* Put set data into set[] */
read = 0;
for(i = 0; i < indexliste; i++) {
for(j = 0; j < list[0][i]; j++) {
switch(list[1][i]) {
case SHIFTA: set[read] = 'a'; break;
case LATCHA: set[read] = 'A'; break;
case SHIFTB: set[read] = 'b'; break;
case LATCHB: set[read] = 'B'; break;
case LATCHC: set[read] = 'C'; break;
}
read++;
}
}
/* Adjust for strings which start with shift characters - make them latch instead */
if(set[0] == 'a') {
i = 0;
do {
set[i] = 'A';
i++;
} while (set[i] == 'a');
}
if(set[0] == 'b') {
i = 0;
do {
set[i] = 'B';
i++;
} while (set[i] == 'b');
}
/* Now we can calculate how long the barcode is going to be - and stop it from
being too long */
last_set = ' ';
last_fset = ' ';
glyph_count = 0.0;
for(i = 0; i < sourcelen; i++) {
if((set[i] == 'a') || (set[i] == 'b')) {
glyph_count = glyph_count + 1.0;
}
if((fset[i] == 'f') || (fset[i] == 'n')) {
glyph_count = glyph_count + 1.0;
}
if(((set[i] == 'A') || (set[i] == 'B')) || (set[i] == 'C')) {
if(set[i] != last_set) {
last_set = set[i];
glyph_count = glyph_count + 1.0;
}
}
if(i == 0) {
if(fset[i] == 'F') {
last_fset = 'F';
glyph_count = glyph_count + 2.0;
}
} else {
if((fset[i] == 'F') && (fset[i - 1] != 'F')) {
last_fset = 'F';
glyph_count = glyph_count + 2.0;
}
if((fset[i] != 'F') && (fset[i - 1] == 'F')) {
last_fset = ' ';
glyph_count = glyph_count + 2.0;
}
}
if(set[i] == 'C') {
glyph_count = glyph_count + 0.5;
} else {
glyph_count = glyph_count + 1.0;
}
}
if(glyph_count > 80.0) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
/* So now we know what start character to use - we can get on with it! */
if(symbol->output_options & READER_INIT) {
/* Reader Initialisation mode */
switch(set[0]) {
case 'A': /* Start A */
concat(dest, C128Table[103]);
values[0] = 103;
current_set = 'A';
concat(dest, C128Table[96]); /* FNC3 */
values[1] = 96;
bar_characters++;
break;
case 'B': /* Start B */
concat(dest, C128Table[104]);
values[0] = 104;
current_set = 'B';
concat(dest, C128Table[96]); /* FNC3 */
values[1] = 96;
bar_characters++;
break;
case 'C': /* Start C */
concat(dest, C128Table[104]); /* Start B */
values[0] = 105;
concat(dest, C128Table[96]); /* FNC3 */
values[1] = 96;
concat(dest, C128Table[99]); /* Code C */
values[2] = 99;
bar_characters += 2;
current_set = 'C';
break;
}
} else {
/* Normal mode */
switch(set[0]) {
case 'A': /* Start A */
concat(dest, C128Table[103]);
values[0] = 103;
current_set = 'A';
break;
case 'B': /* Start B */
concat(dest, C128Table[104]);
values[0] = 104;
current_set = 'B';
break;
case 'C': /* Start C */
concat(dest, C128Table[105]);
values[0] = 105;
current_set = 'C';
break;
}
}
bar_characters++;
last_set = set[0];
if(fset[0] == 'F') {
switch(current_set) {
case 'A':
concat(dest, C128Table[101]);
concat(dest, C128Table[101]);
values[bar_characters] = 101;
values[bar_characters + 1] = 101;
break;
case 'B':
concat(dest, C128Table[100]);
concat(dest, C128Table[100]);
values[bar_characters] = 100;
values[bar_characters + 1] = 100;
break;
}
bar_characters += 2;
f_state = 1;
}
/* Encode the data */
read = 0;
do {
if((read != 0) && (set[read] != current_set))
{ /* Latch different code set */
switch(set[read])
{
case 'A': concat(dest, C128Table[101]);
values[bar_characters] = 101;
bar_characters++;
current_set = 'A';
break;
case 'B': concat(dest, C128Table[100]);
values[bar_characters] = 100;
bar_characters++;
current_set = 'B';
break;
case 'C': concat(dest, C128Table[99]);
values[bar_characters] = 99;
bar_characters++;
current_set = 'C';
break;
}
}
if(read != 0) {
if((fset[read] == 'F') && (f_state == 0)) {
/* Latch beginning of extended mode */
switch(current_set) {
case 'A':
concat(dest, C128Table[101]);
concat(dest, C128Table[101]);
values[bar_characters] = 101;
values[bar_characters + 1] = 101;
break;
case 'B':
concat(dest, C128Table[100]);
concat(dest, C128Table[100]);
values[bar_characters] = 100;
values[bar_characters + 1] = 100;
break;
}
bar_characters += 2;
f_state = 1;
}
if((fset[read] == ' ') && (f_state == 1)) {
/* Latch end of extended mode */
switch(current_set) {
case 'A':
concat(dest, C128Table[101]);
concat(dest, C128Table[101]);
values[bar_characters] = 101;
values[bar_characters + 1] = 101;
break;
case 'B':
concat(dest, C128Table[100]);
concat(dest, C128Table[100]);
values[bar_characters] = 100;
values[bar_characters + 1] = 100;
break;
}
bar_characters += 2;
f_state = 0;
}
}
if((fset[read] == 'f') || (fset[read] == 'n')) {
/* Shift to or from extended mode */
switch(current_set) {
case 'A':
concat(dest, C128Table[101]); /* FNC 4 */
values[bar_characters] = 101;
break;
case 'B':
concat(dest, C128Table[100]); /* FNC 4 */
values[bar_characters] = 100;
break;
}
bar_characters++;
}
if((set[read] == 'a') || (set[read] == 'b')) {
/* Insert shift character */
concat(dest, C128Table[98]);
values[bar_characters] = 98;
bar_characters++;
}
switch(set[read])
{ /* Encode data characters */
case 'a':
case 'A': c128_set_a(source[read], dest, values, &bar_characters);
read++;
break;
case 'b':
case 'B': c128_set_b(source[read], dest, values, &bar_characters);
read++;
break;
case 'C': c128_set_c(source[read], source[read + 1], dest, values, &bar_characters);
read += 2;
break;
}
} while (read < sourcelen);
/* check digit calculation */
total_sum = 0;
/*for(i = 0; i < bar_characters; i++) {
printf("%d\n", values[i]);
}*/
for(i = 0; i < bar_characters; i++)
{
if(i > 0)
{
values[i] *= i;
}
total_sum += values[i];
}
concat(dest, C128Table[total_sum%103]);
/* Stop character */
concat(dest, C128Table[106]);
expand(symbol, dest);
return error_number;
}
int ean_128(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Handle EAN-128 (Now known as GS1-128) */
int i, j, e_count, values[170], bar_characters, read, total_sum;
int error_number, indexchaine, indexliste;
char set[170], mode, last_set;
float glyph_count;
char dest[1000];
int separator_row, linkage_flag, c_count;
#ifndef _MSC_VER
char reduced[length + 1];
#else
char* reduced = (char*)_alloca(length + 1);
#endif
error_number = 0;
strcpy(dest, "");
linkage_flag = 0;
j = 0;
e_count = 0;
bar_characters = 0;
separator_row = 0;
memset(values, 0, sizeof(values));
memset(set, ' ', sizeof(set));
if(length > 160) {
/* This only blocks rediculously long input - the actual length of the
resulting barcode depends on the type of data, so this is trapped later */
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
for(i = 0; i < length; i++) {
if(source[i] == '\0') {
/* Null characters not allowed! */
strcpy(symbol->errtxt, "NULL character in input data");
return ERROR_INVALID_DATA;
}
}
/* if part of a composite symbol make room for the separator pattern */
if(symbol->symbology == BARCODE_EAN128_CC) {
separator_row = symbol->rows;
symbol->row_height[symbol->rows] = 1;
symbol->rows += 1;
}
if(symbol->input_mode != GS1_MODE) {
/* GS1 data has not been checked yet */
error_number = gs1_verify(symbol, source, length, reduced);
if(error_number != 0) { return error_number; }
}
/* Decide on mode using same system as PDF417 and rules of ISO 15417 Annex E */
indexliste = 0;
indexchaine = 0;
mode = parunmodd(reduced[indexchaine]);
if(reduced[indexchaine] == '[') {
mode = ABORC;
}
for(i = 0; i < 170; i++) {
list[0][i] = 0;
}
do {
list[1][indexliste] = mode;
while ((list[1][indexliste] == mode) && (indexchaine < strlen(reduced))) {
list[0][indexliste]++;
indexchaine++;
mode = parunmodd(reduced[indexchaine]);
if(reduced[indexchaine] == '[') { mode = ABORC; }
}
indexliste++;
} while (indexchaine < strlen(reduced));
dxsmooth(&indexliste);
/* Put set data into set[] */
read = 0;
for(i = 0; i < indexliste; i++) {
for(j = 0; j < list[0][i]; j++) {
switch(list[1][i]) {
case SHIFTA: set[read] = 'a'; break;
case LATCHA: set[read] = 'A'; break;
case SHIFTB: set[read] = 'b'; break;
case LATCHB: set[read] = 'B'; break;
case LATCHC: set[read] = 'C'; break;
}
read++;
}
}
/* Watch out for odd-length Mode C blocks */
c_count = 0;
for(i = 0; i < read; i++) {
if(set[i] == 'C') {
if(reduced[i] == '[') {
if(c_count % 2) {
if((i - c_count) != 0) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
}
}
c_count = 0;
} else {
c_count++;
}
} else {
if(c_count % 2) {
if((i - c_count) != 0) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
}
}
c_count = 0;
}
}
if(c_count % 2) {
if((i - c_count) != 0) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
}
}
for(i = 1; i < read - 1; i++) {
if((set[i] == 'C') && ((set[i - 1] == 'B') && (set[i + 1] == 'B'))) {
set[i] = 'B';
}
}
/* for(i = 0; i < read; i++) {
printf("char %c mode %c\n", reduced[i], set[i]);
} */
/* Now we can calculate how long the barcode is going to be - and stop it from
being too long */
last_set = ' ';
glyph_count = 0.0;
for(i = 0; i < strlen(reduced); i++) {
if((set[i] == 'a') || (set[i] == 'b')) {
glyph_count = glyph_count + 1.0;
}
if(((set[i] == 'A') || (set[i] == 'B')) || (set[i] == 'C')) {
if(set[i] != last_set) {
last_set = set[i];
glyph_count = glyph_count + 1.0;
}
}
if((set[i] == 'C') && (reduced[i] != '[')) {
glyph_count = glyph_count + 0.5;
} else {
glyph_count = glyph_count + 1.0;
}
}
if(glyph_count > 80.0) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
/* So now we know what start character to use - we can get on with it! */
switch(set[0])
{
case 'A': /* Start A */
concat(dest, C128Table[103]);
values[0] = 103;
break;
case 'B': /* Start B */
concat(dest, C128Table[104]);
values[0] = 104;
break;
case 'C': /* Start C */
concat(dest, C128Table[105]);
values[0] = 105;
break;
}
bar_characters++;
concat(dest, C128Table[102]);
values[1] = 102;
bar_characters++;
/* Encode the data */
read = 0;
do {
if((read != 0) && (set[read] != set[read - 1]))
{ /* Latch different code set */
switch(set[read])
{
case 'A': concat(dest, C128Table[101]);
values[bar_characters] = 101;
bar_characters++;
break;
case 'B': concat(dest, C128Table[100]);
values[bar_characters] = 100;
bar_characters++;
break;
case 'C': concat(dest, C128Table[99]);
values[bar_characters] = 99;
bar_characters++;
break;
}
}
if((set[read] == 'a') || (set[read] == 'b')) {
/* Insert shift character */
concat(dest, C128Table[98]);
values[bar_characters] = 98;
bar_characters++;
}
if(reduced[read] != '[') {
switch(set[read])
{ /* Encode data characters */
case 'A':
case 'a':
c128_set_a(reduced[read], dest, values, &bar_characters);
read++;
break;
case 'B':
case 'b':
c128_set_b(reduced[read], dest, values, &bar_characters);
read++;
break;
case 'C':
c128_set_c(reduced[read], reduced[read + 1], dest, values, &bar_characters);
read += 2;
break;
}
} else {
concat(dest, C128Table[102]);
values[bar_characters] = 102;
bar_characters++;
read++;
}
} while (read < strlen(reduced));
/* "...note that the linkage flag is an extra code set character between
the last data character and the Symbol Check Character" (GS1 Specification) */
/* Linkage flags in GS1-128 are determined by ISO/IEC 24723 section 7.4 */
switch(symbol->option_1) {
case 1:
case 2:
/* CC-A or CC-B 2D component */
switch(set[strlen(reduced) - 1]) {
case 'A': linkage_flag = 100; break;
case 'B': linkage_flag = 99; break;
case 'C': linkage_flag = 101; break;
}
break;
case 3:
/* CC-C 2D component */
switch(set[strlen(reduced) - 1]) {
case 'A': linkage_flag = 99; break;
case 'B': linkage_flag = 101; break;
case 'C': linkage_flag = 100; break;
}
break;
}
if(linkage_flag != 0) {
concat(dest, C128Table[linkage_flag]);
values[bar_characters] = linkage_flag;
bar_characters++;
}
/*for(i = 0; i < bar_characters; i++) {
printf("[%d] ", values[i]);
}
printf("\n");*/
/* check digit calculation */
total_sum = 0;
for(i = 0; i < bar_characters; i++)
{
if(i > 0)
{
values[i] *= i;
}
total_sum += values[i];
}
concat(dest, C128Table[total_sum%103]);
values[bar_characters] = total_sum % 103;
bar_characters++;
/* Stop character */
concat(dest, C128Table[106]);
values[bar_characters] = 106;
bar_characters++;
expand(symbol, dest);
/* Add the separator pattern for composite symbols */
if(symbol->symbology == BARCODE_EAN128_CC) {
for(i = 0; i < symbol->width; i++) {
if(!(module_is_set(symbol, separator_row + 1, i))) {
set_module(symbol, separator_row, i);
}
}
}
for(i = 0; i < length; i++) {
if((source[i] != '[') && (source[i] != ']')) {
symbol->text[i] = source[i];
}
if(source[i] == '[') {
symbol->text[i] = '(';
}
if(source[i] == ']') {
symbol->text[i] = ')';
}
}
return error_number;
}
int nve_18(struct zint_symbol *symbol, unsigned char source[], int length)
{
/* Add check digit if encoding an NVE18 symbol */
int error_number, zeroes, i, nve_check, total_sum, sourcelen;
unsigned char ean128_equiv[25];
memset(ean128_equiv, 0, 25);
sourcelen = length;
if(sourcelen > 17) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
zeroes = 17 - sourcelen;
strcpy((char *)ean128_equiv, "[00]");
memset(ean128_equiv + 4, '0', zeroes);
strcpy((char*)ean128_equiv + 4 + zeroes, (char*)source);
total_sum = 0;
for(i = sourcelen - 1; i >= 0; i--)
{
total_sum += ctoi(source[i]);
if(!((i%2) == 1)) {
total_sum += 2 * ctoi(source[i]);
}
}
nve_check = 10 - total_sum % 10;
if(nve_check == 10) { nve_check = 0; }
ean128_equiv[21] = itoc(nve_check);
ean128_equiv[22] = '\0';
error_number = ean_128(symbol, ean128_equiv, ustrlen(ean128_equiv));
return error_number;
}
int ean_14(struct zint_symbol *symbol, unsigned char source[], int length)
{
/* EAN-14 - A version of EAN-128 */
int i, count, check_digit;
int error_number, zeroes;
unsigned char ean128_equiv[20];
if(length > 13) {
strcpy(symbol->errtxt, "Input wrong length");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid character in data");
return error_number;
}
zeroes = 13 - length;
strcpy((char*)ean128_equiv, "[01]");
memset(ean128_equiv + 4, '0', zeroes);
ustrcpy(ean128_equiv + 4 + zeroes, source);
count = 0;
for (i = length - 1; i >= 0; i--)
{
count += ctoi(source[i]);
if (!((i % 2) == 1))
{
count += 2 * ctoi(source[i]);
}
}
check_digit = 10 - (count % 10);
if (check_digit == 10) { check_digit = 0; }
ean128_equiv[17] = itoc(check_digit);
ean128_equiv[18] = '\0';
error_number = ean_128(symbol, ean128_equiv, ustrlen(ean128_equiv));
return error_number;
}

622
backend/code16k.c Normal file
View file

@ -0,0 +1,622 @@
/* code16k.c - Handles Code 16k stacked symbology */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* Updated to comply with BS EN 12323:2005 */
/* up to 77 characters or 154 numbers */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#define TRUE 1
#define FALSE 0
#define SHIFTA 90
#define LATCHA 91
#define SHIFTB 92
#define LATCHB 93
#define SHIFTC 94
#define LATCHC 95
#define AORB 96
#define ABORC 97
#define CANDB 98
#define CANDBB 99
static int list[2][170];
/* EN 12323 Table 1 - "Code 16K" character encodations */
static char *C16KTable[107] = {"212222", "222122", "222221", "121223", "121322", "131222", "122213",
"122312", "132212", "221213", "221312", "231212", "112232", "122132", "122231", "113222",
"123122", "123221", "223211", "221132", "221231", "213212", "223112", "312131", "311222",
"321122", "321221", "312212", "322112", "322211", "212123", "212321", "232121", "111323",
"131123", "131321", "112313", "132113", "132311", "211313", "231113", "231311", "112133",
"112331", "132131", "113123", "113321", "133121", "313121", "211331", "231131", "213113",
"213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111", "314111",
"221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214",
"112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112",
"134111", "111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112",
"421211", "212141", "214121", "412121", "111143", "111341", "131141", "114113", "114311",
"411113", "411311", "113141", "114131", "311141", "411131", "211412", "211214", "211232",
"211133"};
/* EN 12323 Table 3 and Table 4 - Start patterns and stop patterns */
static char *C16KStartStop[8] = {"3211", "2221", "2122", "1411", "1132", "1231", "1114", "3112"};
/* EN 12323 Table 5 - Start and stop values defining row numbers */
static int C16KStartValues[16] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7};
static int C16KStopValues[16] = {0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 0, 1, 2, 3};
void grwp16(int *indexliste)
{
int i, j;
/* bring together same type blocks */
if(*(indexliste) > 1) {
i = 1;
while(i < *(indexliste)) {
if(list[1][i - 1] == list[1][i]) {
/* bring together */
list[0][i - 1] = list[0][i - 1] + list[0][i];
j = i + 1;
/* decreace the list */
while(j < *(indexliste)) {
list[0][j - 1] = list[0][j];
list[1][j - 1] = list[1][j];
j++;
}
*(indexliste) = *(indexliste) - 1;
i--;
}
i++;
}
}
}
void dxsmooth16(int *indexliste)
{ /* Implements rules from ISO 15417 Annex E */
int i, current, last, next, length;
for(i = 0; i < *(indexliste); i++) {
current = list[1][i];
length = list[0][i];
if(i != 0) { last = list[1][i - 1]; } else { last = FALSE; }
if(i != *(indexliste) - 1) { next = list[1][i + 1]; } else { next = FALSE; }
if(i == 0) { /* first block */
if((*(indexliste) == 1) && ((length == 2) && (current == ABORC))) { /* Rule 1a */ list[1][i] = LATCHC; }
if(current == ABORC) {
if(length >= 4) {/* Rule 1b */ list[1][i] = LATCHC; } else { list[1][i] = AORB; current = AORB; }
}
if(current == SHIFTA) { /* Rule 1c */ list[1][i] = LATCHA; }
if((current == AORB) && (next == SHIFTA)) { /* Rule 1c */ list[1][i] = LATCHA; current = LATCHA; }
if(current == AORB) { /* Rule 1d */ list[1][i] = LATCHB; }
} else {
if((current == ABORC) && (length >= 4)) { /* Rule 3 */ list[1][i] = LATCHC; current = LATCHC; }
if(current == ABORC) { list[1][i] = AORB; current = AORB; }
if((current == AORB) && (last == LATCHA)) { list[1][i] = LATCHA; current = LATCHA; }
if((current == AORB) && (last == LATCHB)) { list[1][i] = LATCHB; current = LATCHB; }
if((current == AORB) && (next == SHIFTA)) { list[1][i] = LATCHA; current = LATCHA; }
if((current == AORB) && (next == SHIFTB)) { list[1][i] = LATCHB; current = LATCHB; }
if(current == AORB) { list[1][i] = LATCHB; current = LATCHB; }
if((current == SHIFTA) && (length > 1)) { /* Rule 4 */ list[1][i] = LATCHA; current = LATCHA; }
if((current == SHIFTB) && (length > 1)) { /* Rule 5 */ list[1][i] = LATCHB; current = LATCHB; }
if((current == SHIFTA) && (last == LATCHA)) { list[1][i] = LATCHA; current = LATCHA; }
if((current == SHIFTB) && (last == LATCHB)) { list[1][i] = LATCHB; current = LATCHB; }
if((current == SHIFTA) && (last == LATCHC)) { list[1][i] = LATCHA; current = LATCHA; }
if((current == SHIFTB) && (last == LATCHC)) { list[1][i] = LATCHB; current = LATCHB; }
} /* Rule 2 is implimented elsewhere, Rule 6 is implied */
}
grwp16(indexliste);
}
void c16k_set_a(unsigned char source, unsigned int values[], unsigned int *bar_chars)
{
if(source > 127) {
if(source < 160) {
values[(*bar_chars)] = source + 64 - 128;
} else {
values[(*bar_chars)] = source - 32 - 128;
}
} else {
if(source < 32) {
values[(*bar_chars)] = source + 64;
} else {
values[(*bar_chars)] = source - 32;
}
}
(*bar_chars)++;
}
void c16k_set_b(unsigned char source, unsigned int values[], unsigned int *bar_chars)
{
if(source > 127) {
values[(*bar_chars)] = source - 32 - 128;
} else {
values[(*bar_chars)] = source - 32;
}
(*bar_chars)++;
}
void c16k_set_c(unsigned char source_a, unsigned char source_b, unsigned int values[], unsigned int *bar_chars)
{
int weight;
weight = (10 * ctoi(source_a)) + ctoi(source_b);
values[(*bar_chars)] = weight;
(*bar_chars)++;
}
int code16k(struct zint_symbol *symbol, unsigned char source[], int length)
{
char width_pattern[100];
int current_row, rows_needed, flip_flop, looper, first_check, second_check;
int indexliste, indexchaine, pads_needed, f_state;
char set[160] = { ' ' }, fset[160] = { ' ' }, mode, last_set, last_fset, current_set;
unsigned int i, j, k, m, e_count, read, mx_reader, writer;
unsigned int values[160] = { 0 };
unsigned int bar_characters;
float glyph_count;
int errornum, first_sum, second_sum;
int input_length;
int gs1, c_count;
errornum = 0;
strcpy(width_pattern, "");
input_length = length;
if(symbol->input_mode == GS1_MODE) { gs1 = 1; } else { gs1 = 0; }
if(input_length > 157) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
e_count = 0;
bar_characters = 0;
/* Detect extended ASCII characters */
for(i = 0; i < input_length; i++) {
if(source[i] >=128) {
fset[i] = 'f';
}
}
fset[i] = '\0';
/* Decide when to latch to extended mode */
for(i = 0; i < input_length; i++) {
j = 0;
if(fset[i] == 'f') {
do {
j++;
} while(fset[i + j] == 'f');
if((j >= 5) || ((j >= 3) && ((i + j) == (input_length - 1)))) {
for(k = 0; k <= j; k++) {
fset[i + k] = 'F';
}
}
}
}
/* Decide if it is worth reverting to 646 encodation for a few characters */
if(input_length > 1) {
for(i = 1; i < input_length; i++) {
if((fset[i - 1] == 'F') && (fset[i] == ' ')) {
/* Detected a change from 8859-1 to 646 - count how long for */
for(j = 0; (fset[i + j] == ' ') && ((i + j) < input_length); j++);
if((j < 5) || ((j < 3) && ((i + j) == (input_length - 1)))) {
/* Change to shifting back rather than latching back */
for(k = 0; k < j; k++) {
fset[i + k] = 'n';
}
}
}
}
}
/* Detect mode A, B and C characters */
indexliste = 0;
indexchaine = 0;
mode = parunmodd(source[indexchaine]);
if((gs1) && (source[indexchaine] == '[')) { mode = ABORC; } /* FNC1 */
for(i = 0; i < 160; i++) {
list[0][i] = 0;
}
do {
list[1][indexliste] = mode;
while ((list[1][indexliste] == mode) && (indexchaine < input_length)) {
list[0][indexliste]++;
indexchaine++;
mode = parunmodd(source[indexchaine]);
if((gs1) && (source[indexchaine] == '[')) { mode = ABORC; } /* FNC1 */
}
indexliste++;
} while (indexchaine < input_length);
dxsmooth16(&indexliste);
/* Put set data into set[] */
read = 0;
for(i = 0; i < indexliste; i++) {
for(j = 0; j < list[0][i]; j++) {
switch(list[1][i]) {
case SHIFTA: set[read] = 'a'; break;
case LATCHA: set[read] = 'A'; break;
case SHIFTB: set[read] = 'b'; break;
case LATCHB: set[read] = 'B'; break;
case LATCHC: set[read] = 'C'; break;
}
read++;
}
}
/* Adjust for strings which start with shift characters - make them latch instead */
if(set[0] == 'a') {
i = 0;
do {
set[i] = 'A';
i++;
} while (set[i] == 'a');
}
if(set[0] == 'b') {
i = 0;
do {
set[i] = 'B';
i++;
} while (set[i] == 'b');
}
/* Watch out for odd-length Mode C blocks */
c_count = 0;
for(i = 0; i < read; i++) {
if(set[i] == 'C') {
if(source[i] == '[') {
if(c_count % 2) {
if((i - c_count) != 0) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
}
}
c_count = 0;
} else {
c_count++;
}
} else {
if(c_count % 2) {
if((i - c_count) != 0) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
}
}
c_count = 0;
}
}
if(c_count % 2) {
if((i - c_count) != 0) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
}
}
for(i = 1; i < read - 1; i++) {
if((set[i] == 'C') && ((set[i - 1] == 'B') && (set[i + 1] == 'B'))) {
set[i] = 'B';
}
}
/* Make sure the data will fit in the symbol */
last_set = ' ';
last_fset = ' ';
glyph_count = 0.0;
for(i = 0; i < input_length; i++) {
if((set[i] == 'a') || (set[i] == 'b')) {
glyph_count = glyph_count + 1.0;
}
if((fset[i] == 'f') || (fset[i] == 'n')) {
glyph_count = glyph_count + 1.0;
}
if(((set[i] == 'A') || (set[i] == 'B')) || (set[i] == 'C')) {
if(set[i] != last_set) {
last_set = set[i];
glyph_count = glyph_count + 1.0;
}
}
if(i == 0) {
if((set[i] == 'B') && (set[1] == 'C')) {
glyph_count = glyph_count - 1.0;
}
if((set[i] == 'B') && (set[1] == 'B')) {
if(set[2] == 'C') {
glyph_count = glyph_count - 1.0;
}
}
if(fset[i] == 'F') {
last_fset = 'F';
glyph_count = glyph_count + 2.0;
}
} else {
if((fset[i] == 'F') && (fset[i - 1] != 'F')) {
last_fset = 'F';
glyph_count = glyph_count + 2.0;
}
if((fset[i] != 'F') && (fset[i - 1] == 'F')) {
last_fset = ' ';
glyph_count = glyph_count + 2.0;
}
}
if((set[i] == 'C') && (!((gs1) && (source[i] == '[')))) {
glyph_count = glyph_count + 0.5;
} else {
glyph_count = glyph_count + 1.0;
}
}
if((gs1) && (set[0] != 'A')) {
/* FNC1 can be integrated with mode character */
glyph_count--;
}
if(glyph_count > 77.0) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
/* Calculate how tall the symbol will be */
glyph_count = glyph_count + 2.0;
i = glyph_count;
rows_needed = (i/5);
if(i%5 > 0) { rows_needed++; }
if(rows_needed == 1) {
rows_needed = 2;
}
/* start with the mode character - Table 2 */
m = 0;
switch(set[0]) {
case 'A': m = 0; break;
case 'B': m = 1; break;
case 'C': m = 2; break;
}
if(symbol->output_options & READER_INIT) {
if(m == 2) { m = 5; }
if(gs1) {
strcpy(symbol->errtxt, "Cannot use both GS1 mode and Reader Initialisation");
return ERROR_INVALID_OPTION;
} else {
if((set[0] == 'B') && (set[1] == 'C')) { m = 6; }
}
values[bar_characters] = (7 * (rows_needed - 2)) + m; /* see 4.3.4.2 */
values[bar_characters + 1] = 96; /* FNC3 */
bar_characters += 2;
} else {
if(gs1) {
/* Integrate FNC1 */
switch(set[0]) {
case 'B': m = 3; break;
case 'C': m = 4; break;
}
} else {
if((set[0] == 'B') && (set[1] == 'C')) { m = 5; }
if(((set[0] == 'B') && (set[1] == 'B')) && (set[2] == 'C')) { m = 6; }
}
values[bar_characters] = (7 * (rows_needed - 2)) + m; /* see 4.3.4.2 */
bar_characters++;
}
current_set = set[0];
f_state = 0; /* f_state remembers if we are in Extended ASCII mode (value 1) or
in ISO/IEC 646 mode (value 0) */
if(fset[0] == 'F') {
switch(current_set) {
case 'A':
values[bar_characters] = 101;
values[bar_characters + 1] = 101;
break;
case 'B':
values[bar_characters] = 100;
values[bar_characters + 1] = 100;
break;
}
bar_characters += 2;
f_state = 1;
}
read = 0;
/* Encode the data */
do {
if((read != 0) && (set[read] != set[read - 1]))
{ /* Latch different code set */
switch(set[read])
{
case 'A':
values[bar_characters] = 101;
bar_characters++;
current_set = 'A';
break;
case 'B':
values[bar_characters] = 100;
bar_characters++;
current_set = 'B';
break;
case 'C':
if(!((read == 1) && (set[0] == 'B'))) { /* Not Mode C/Shift B */
if(!((read == 2) && ((set[0] == 'B') && (set[1] == 'B')))) {
/* Not Mode C/Double Shift B */
values[bar_characters] = 99;
bar_characters++;
}
}
current_set = 'C';
break;
}
}
/* printf("tp8\n"); */
if(read != 0) {
if((fset[read] == 'F') && (f_state == 0)) {
/* Latch beginning of extended mode */
switch(current_set) {
case 'A':
values[bar_characters] = 101;
values[bar_characters + 1] = 101;
break;
case 'B':
values[bar_characters] = 100;
values[bar_characters + 1] = 100;
break;
}
bar_characters += 2;
f_state = 1;
}
if((fset[read] == ' ') && (f_state == 1)) {
/* Latch end of extended mode */
switch(current_set) {
case 'A':
values[bar_characters] = 101;
values[bar_characters + 1] = 101;
break;
case 'B':
values[bar_characters] = 100;
values[bar_characters + 1] = 100;
break;
}
bar_characters += 2;
f_state = 0;
}
}
if((fset[i] == 'f') || (fset[i] == 'n')) {
/* Shift extended mode */
switch(current_set) {
case 'A':
values[bar_characters] = 101; /* FNC 4 */
break;
case 'B':
values[bar_characters] = 100; /* FNC 4 */
break;
}
bar_characters++;
}
if((set[i] == 'a') || (set[i] == 'b')) {
/* Insert shift character */
values[bar_characters] = 98;
bar_characters++;
}
if(!((gs1) && (source[read] == '['))) {
switch(set[read])
{ /* Encode data characters */
case 'A':
case 'a':
c16k_set_a(source[read], values, &bar_characters);
read++;
break;
case 'B':
case 'b':
c16k_set_b(source[read], values, &bar_characters);
read++;
break;
case 'C': c16k_set_c(source[read], source[read + 1], values, &bar_characters);
read += 2;
break;
}
} else {
values[bar_characters] = 102;
bar_characters++;
read++;
}
/* printf("tp9 read=%d surrent set=%c\n", read, set[read]); */
} while (read < ustrlen(source));
pads_needed = 5 - ((bar_characters + 2) % 5);
if(pads_needed == 5) {
pads_needed = 0;
}
if((bar_characters + pads_needed) < 8) {
pads_needed += 8 - (bar_characters + pads_needed);
}
for(i = 0; i < pads_needed; i++) {
values[bar_characters] = 106;
bar_characters++;
}
/* Calculate check digits */
first_sum = 0;
second_sum = 0;
for(i = 0; i < bar_characters; i++)
{
first_sum += (i+2) * values[i];
second_sum += (i+1) * values[i];
}
first_check = first_sum % 107;
second_sum += first_check * (bar_characters + 1);
second_check = second_sum % 107;
values[bar_characters] = first_check;
values[bar_characters + 1] = second_check;
bar_characters += 2;
for(current_row = 0; current_row < rows_needed; current_row++) {
strcpy(width_pattern, "");
concat(width_pattern, C16KStartStop[C16KStartValues[current_row]]);
concat(width_pattern, "1");
for(i = 0; i < 5; i++) {
concat(width_pattern, C16KTable[values[(current_row * 5) + i]]);
/* printf("[%d] ", values[(current_row * 5) + i]); */
}
concat(width_pattern, C16KStartStop[C16KStopValues[current_row]]);
/* printf("\n"); */
/* Write the information into the symbol */
writer = 0;
flip_flop = 1;
for (mx_reader = 0; mx_reader < strlen(width_pattern); mx_reader++) {
for(looper = 0; looper < ctoi(width_pattern[mx_reader]); looper++) {
if(flip_flop == 1) {
set_module(symbol, current_row, writer);
writer++; }
else {
writer++; }
}
if(flip_flop == 0) { flip_flop = 1; } else { flip_flop = 0; }
}
symbol->row_height[current_row] = 10;
}
symbol->rows = rows_needed;
symbol->width = 70;
return errornum;
}

315
backend/code49.c Normal file
View file

@ -0,0 +1,315 @@
/* code49.c - Handles Code 49 */
/*
libzint - the open source barcode library
Copyright (C) 2009 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#include "code49.h"
#define INSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%!&*"
/* "!" represents Shift 1 and "&" represents Shift 2, "*" represents FNC1 */
int code_49(struct zint_symbol *symbol, unsigned char source[], int length)
{
int i, j, rows, M, x_count, y_count, z_count, posn_val, local_value, h;
char intermediate[170];
int codewords[170], codeword_count;
int c_grid[8][8]; /* Refers to table 3 */
int w_grid[8][4]; /* Refets to table 2 */
int pad_count = 0;
char pattern[40];
int gs1;
if(length > 81) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
if(symbol->input_mode == GS1_MODE) { gs1 = 1; } else { gs1 = 0; }
strcpy(intermediate, gs1 ? "*" : ""); /* FNC1 */
for(i = 0; i < length; i++) {
if(source[i] > 127) {
strcpy(symbol->errtxt, "Invalid characters in input data");
return ERROR_INVALID_DATA;
}
if(gs1 && (source[i] == '['))
concat(intermediate, "*"); /* FNC1 */
else
concat(intermediate, c49_table7[source[i]]);
}
codeword_count = 0;
i = 0;
h = strlen(intermediate);
do {
if((intermediate[i] >= '0') && (intermediate[i] <= '9')) {
/* Numeric data */
for(j = 0; (intermediate[i + j] >= '0') && (intermediate[i + j] <= '9'); j++);
if(j >= 5) {
/* Use Numeric Encodation Method */
int block_count, c;
int block_remain;
int block_value;
codewords[codeword_count] = 48; /* Numeric Shift */
codeword_count++;
block_count = j / 5;
block_remain = j % 5;
for(c = 0; c < block_count; c++) {
if((c == block_count - 1) && (block_remain == 2)) {
/* Rule (d) */
block_value = 100000;
block_value += ctoi(intermediate[i]) * 1000;
block_value += ctoi(intermediate[i + 1]) * 100;
block_value += ctoi(intermediate[i + 2]) * 10;
block_value += ctoi(intermediate[i + 3]);
codewords[codeword_count] = block_value / (48 * 48);
block_value = block_value - (48 * 48) * codewords[codeword_count];
codeword_count++;
codewords[codeword_count] = block_value / 48;
block_value = block_value - 48 * codewords[codeword_count];
codeword_count++;
codewords[codeword_count] = block_value;
codeword_count++;
i += 4;
block_value = ctoi(intermediate[i]) * 100;
block_value += ctoi(intermediate[i + 1]) * 10;
block_value += ctoi(intermediate[i + 2]);
codewords[codeword_count] = block_value / 48;
block_value = block_value - 48 * codewords[codeword_count];
codeword_count++;
codewords[codeword_count] = block_value;
codeword_count++;
i += 3;
} else {
block_value = ctoi(intermediate[i]) * 10000;
block_value += ctoi(intermediate[i + 1]) * 1000;
block_value += ctoi(intermediate[i + 2]) * 100;
block_value += ctoi(intermediate[i + 3]) * 10;
block_value += ctoi(intermediate[i + 4]);
codewords[codeword_count] = block_value / (48 * 48);
block_value = block_value - (48 * 48) * codewords[codeword_count];
codeword_count++;
codewords[codeword_count] = block_value / 48;
block_value = block_value - 48 * codewords[codeword_count];
codeword_count++;
codewords[codeword_count] = block_value;
codeword_count++;
i += 5;
}
}
switch(block_remain) {
case 1:
/* Rule (a) */
codewords[codeword_count] = posn(INSET, intermediate[i]);
codeword_count++;
i++;
break;
case 3:
/* Rule (b) */
block_value = ctoi(intermediate[i]) * 100;
block_value += ctoi(intermediate[i + 1]) * 10;
block_value += ctoi(intermediate[i + 2]);
codewords[codeword_count] = block_value / 48;
block_value = block_value - 48 * codewords[codeword_count];
codeword_count++;
codewords[codeword_count] = block_value;
codeword_count++;
i += 3;
break;
case 4:
/* Rule (c) */
block_value = 100000;
block_value += ctoi(intermediate[i]) * 1000;
block_value += ctoi(intermediate[i + 1]) * 100;
block_value += ctoi(intermediate[i + 2]) * 10;
block_value += ctoi(intermediate[i + 3]);
codewords[codeword_count] = block_value / (48 * 48);
block_value = block_value - (48 * 48) * codewords[codeword_count];
codeword_count++;
codewords[codeword_count] = block_value / 48;
block_value = block_value - 48 * codewords[codeword_count];
codeword_count++;
codewords[codeword_count] = block_value;
codeword_count++;
i += 4;
break;
}
if(i < h) {
/* There is more to add */
codewords[codeword_count] = 48; /* Numeric Shift */
codeword_count++;
}
} else {
codewords[codeword_count] = posn(INSET, intermediate[i]);
codeword_count++;
i++;
}
} else {
codewords[codeword_count] = posn(INSET, intermediate[i]);
codeword_count++;
i++;
}
} while(i < h);
switch(codewords[0]) { /* Set starting mode value */
case 48: M = 2;
case 43: M = 4;
case 44: M = 5;
default: M = 0;
}
if(M != 0) {
for(i = 0; i < codeword_count; i++) {
codewords[i] = codewords[i + 1];
}
codeword_count--;
}
if(codeword_count > 49) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
/* Place codewords in code character array (c grid) */
rows = 0;
do{
for(i = 0; i < 7; i++) {
if(((rows * 7) + i) < codeword_count) {
c_grid[rows][i] = codewords[(rows * 7) + i];
} else {
c_grid[rows][i] = 48; /* Pad */
pad_count++;
}
}
rows++;
} while ((rows * 7) < codeword_count);
if((((rows <= 6) && (pad_count < 5))) || (rows > 6) || (rows == 1)) {
/* Add a row */
for(i = 0; i < 7; i++) {
c_grid[rows][i] = 48; /* Pad */
}
rows++;
}
/* Add row count and mode character */
c_grid[rows - 1][6] = (7 * (rows - 2)) + M;
/* Add row check character */
for(i = 0; i < rows - 1; i++) {
int row_sum = 0;
for(j = 0; j < 7; j++) {
row_sum += c_grid[i][j];
}
c_grid[i][7] = row_sum % 49;
}
/* Calculate Symbol Check Characters */
posn_val = 0;
x_count = c_grid[rows - 1][6] * 20;
y_count = c_grid[rows - 1][6] * 16;
z_count = c_grid[rows - 1][6] * 38;
for(i = 0; i < rows - 1; i++) {
for(j = 0; j < 4; j++) {
local_value = (c_grid[i][2 * j] * 49) + c_grid[i][(2 * j) + 1];
x_count += c49_x_weight[posn_val] * local_value;
y_count += c49_y_weight[posn_val] * local_value;
z_count += c49_z_weight[posn_val] * local_value;
posn_val++;
}
}
if(rows > 6) {
/* Add Z Symbol Check */
c_grid[rows - 1][0] = (z_count % 2401) / 49;
c_grid[rows - 1][1] = (z_count % 2401) % 49;
}
local_value = (c_grid[rows - 1][0] * 49) + c_grid[rows - 1][1];
x_count += c49_x_weight[posn_val] * local_value;
y_count += c49_y_weight[posn_val] * local_value;
posn_val++;
/* Add Y Symbol Check */
c_grid[rows - 1][2] = (y_count % 2401) / 49;
c_grid[rows - 1][3] = (y_count % 2401) % 49;
local_value = (c_grid[rows - 1][2] * 49) + c_grid[rows - 1][3];
x_count += c49_x_weight[posn_val] * local_value;
/* Add X Symbol Check */
c_grid[rows - 1][4] = (x_count % 2401) / 49;
c_grid[rows - 1][5] = (x_count % 2401) % 49;
/* Add last row check character */
j = 0;
for(i = 0; i < 7; i++) {
j += c_grid[rows - 1][i];
}
c_grid[rows - 1][7] = j % 49;
/* Transfer data to symbol character array (w grid) */
for(i = 0; i < rows; i++) {
for(j = 0; j < 4; j ++) {
w_grid[i][j] = (c_grid[i][2 * j] * 49) + c_grid[i][(2 * j) + 1];
}
}
for(i = 0; i < rows; i++) {
strcpy(pattern, "11"); /* Start character */
for(j = 0; j < 4; j++) {
if(i != (rows - 1)) {
if(c49_table4[i][j] == 'E') {
/* Even Parity */
concat(pattern, c49_appxe_even[w_grid[i][j]]);
} else {
/* Odd Parity */
concat(pattern, c49_appxe_odd[w_grid[i][j]]);
}
} else {
/* Last row uses all even parity */
concat(pattern, c49_appxe_even[w_grid[i][j]]);
}
}
concat(pattern, "4"); /* Stop character */
/* Expand into symbol */
symbol->row_height[i] = 10;
expand(symbol, pattern);
}
symbol->whitespace_width = 10;
symbol->output_options = BARCODE_BIND;
symbol->border_width = 2;
return 0;
}

1175
backend/code49.h Normal file

File diff suppressed because it is too large Load diff

397
backend/common.c Normal file
View file

@ -0,0 +1,397 @@
/* common.c - Contains functions needed for a number of barcodes */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
int ustrlen(unsigned char data[]) {
/* Local replacement for strlen() with unsigned char strings */
int i;
for (i=0;data[i];i++);
return i;
}
void ustrcpy(unsigned char target[], unsigned char source[]) {
/* Local replacement for strcpy() with unsigned char strings */
int i, len;
len = ustrlen(source);
for(i = 0; i < len; i++) {
target[i] = source[i];
}
target[i] = '\0';
}
void concat(char dest[], char source[])
{ /* Concatinates dest[] with the contents of source[], copying /0 as well */
unsigned int i, j, n;
j = strlen(dest);
n = strlen(source);
for(i = 0; i <= n; i++) {
dest[i + j] = source[i]; }
}
void uconcat(unsigned char dest[], unsigned char source[])
{ /* Concatinates dest[] with the contents of source[], copying /0 as well */
unsigned int i, j;
j = ustrlen(dest);
for(i = 0; i <= ustrlen(source); i++) {
dest[i + j] = source[i]; }
}
int ctoi(char source)
{ /* Converts a character 0-9 to its equivalent integer value */
if((source >= '0') && (source <= '9'))
return (source - '0');
return(source - 'A' + 10);
}
char itoc(int source)
{ /* Converts an integer value to its hexadecimal character */
if ((source >= 0) && (source <= 9)) {
return ('0' + source); }
else {
return ('A' + (source - 10)); }
}
void to_upper(unsigned char source[])
{ /* Converts lower case characters to upper case in a string source[] */
unsigned int i, src_len = ustrlen(source);
for (i = 0; i < src_len; i++) {
if ((source[i] >= 'a') && (source[i] <= 'z')) {
source [i] = (source[i] - 'a') + 'A'; }
}
}
int is_sane(char test_string[], unsigned char source[], int length)
{ /* Verifies that a string only uses valid characters */
unsigned int i, j, latch;
unsigned int lt = strlen(test_string);
for(i = 0; i < length; i++) {
latch = FALSE;
for(j = 0; j < lt; j++) {
if (source[i] == test_string[j]) {
latch = TRUE;
break;
}
}
if (!(latch)) {
return ERROR_INVALID_DATA;
}
}
return 0;
}
int posn(char set_string[], char data)
{ /* Returns the position of data in set_string */
unsigned int i, n = strlen(set_string);
for(i = 0; i < n; i++) {
if (data == set_string[i]) { return i; } }
return 0;
}
void lookup(char set_string[], char *table[], char data, char dest[])
{ /* Replaces huge switch statements for looking up in tables */
unsigned int i, n = strlen(set_string);
for(i = 0; i < n; i++) {
if (data == set_string[i]) { concat(dest, table[i]); } }
}
int module_is_set(struct zint_symbol *symbol, int y_coord, int x_coord)
{
return (symbol->encoded_data[y_coord][x_coord / 7] & (1 << (x_coord % 7))) ? 1 : 0;
#if 0
switch(x_sub) {
case 0: if((symbol->encoded_data[y_coord][x_char] & 0x01) != 0) { result = 1; } break;
case 1: if((symbol->encoded_data[y_coord][x_char] & 0x02) != 0) { result = 1; } break;
case 2: if((symbol->encoded_data[y_coord][x_char] & 0x04) != 0) { result = 1; } break;
case 3: if((symbol->encoded_data[y_coord][x_char] & 0x08) != 0) { result = 1; } break;
case 4: if((symbol->encoded_data[y_coord][x_char] & 0x10) != 0) { result = 1; } break;
case 5: if((symbol->encoded_data[y_coord][x_char] & 0x20) != 0) { result = 1; } break;
case 6: if((symbol->encoded_data[y_coord][x_char] & 0x40) != 0) { result = 1; } break;
}
return result;
#endif
}
void set_module(struct zint_symbol *symbol, int y_coord, int x_coord)
{
if(module_is_set(symbol, y_coord, x_coord)) { return; }
symbol->encoded_data[y_coord][x_coord / 7] += 1 << (x_coord % 7);
#if 0
int x_char, x_sub;
x_char = x_coord / 7;
x_sub = x_coord % 7;
switch(x_sub) {
case 0: symbol->encoded_data[y_coord][x_char] += 0x01; break;
case 1: symbol->encoded_data[y_coord][x_char] += 0x02; break;
case 2: symbol->encoded_data[y_coord][x_char] += 0x04; break;
case 3: symbol->encoded_data[y_coord][x_char] += 0x08; break;
case 4: symbol->encoded_data[y_coord][x_char] += 0x10; break;
case 5: symbol->encoded_data[y_coord][x_char] += 0x20; break;
case 6: symbol->encoded_data[y_coord][x_char] += 0x40; break;
} /* The last binary digit is reserved for colour barcodes */
#endif
}
void unset_module(struct zint_symbol *symbol, int y_coord, int x_coord)
{
if(!(module_is_set(symbol, y_coord, x_coord))) { return; }
symbol->encoded_data[y_coord][x_coord / 7] -= 1 << (x_coord % 7);
#if 0
int x_char, x_sub;
x_char = x_coord / 7;
x_sub = x_coord % 7;
switch(x_sub) {
case 0: symbol->encoded_data[y_coord][x_char] -= 0x01; break;
case 1: symbol->encoded_data[y_coord][x_char] -= 0x02; break;
case 2: symbol->encoded_data[y_coord][x_char] -= 0x04; break;
case 3: symbol->encoded_data[y_coord][x_char] -= 0x08; break;
case 4: symbol->encoded_data[y_coord][x_char] -= 0x10; break;
case 5: symbol->encoded_data[y_coord][x_char] -= 0x20; break;
case 6: symbol->encoded_data[y_coord][x_char] -= 0x40; break;
} /* The last binary digit is reserved for colour barcodes */
#endif
}
void expand(struct zint_symbol *symbol, char data[])
{ /* Expands from a width pattern to a bit pattern */
unsigned int reader, n = strlen(data);
int writer, i;
char latch;
writer = 0;
latch = '1';
for(reader = 0; reader < n; reader++) {
for(i = 0; i < ctoi(data[reader]); i++) {
if(latch == '1') { set_module(symbol, symbol->rows, writer); }
writer++;
}
if(latch == '1') {
latch = '0';
} else {
latch = '1';
}
}
if(symbol->symbology != BARCODE_PHARMA) {
if(writer > symbol->width) {
symbol->width = writer;
}
} else {
/* Pharmacode One ends with a space - adjust for this */
if(writer > symbol->width + 2) {
symbol->width = writer - 2;
}
}
symbol->rows = symbol->rows + 1;
}
int is_stackable(int symbology) {
/* Indicates which symbologies can have row binding */
if(symbology < BARCODE_PDF417) { return 1; }
if(symbology == BARCODE_CODE128B) { return 1; }
if(symbology == BARCODE_ISBNX) { return 1; }
if(symbology == BARCODE_EAN14) { return 1; }
if(symbology == BARCODE_NVE18) { return 1; }
if(symbology == BARCODE_KOREAPOST) { return 1; }
if(symbology == BARCODE_PLESSEY) { return 1; }
if(symbology == BARCODE_TELEPEN_NUM) { return 1; }
if(symbology == BARCODE_ITF14) { return 1; }
if(symbology == BARCODE_CODE32) { return 1; }
return 0;
}
int is_extendable(int symbology) {
/* Indicates which symbols can have addon */
if(symbology == BARCODE_EANX) { return 1; }
if(symbology == BARCODE_UPCA) { return 1; }
if(symbology == BARCODE_UPCE) { return 1; }
if(symbology == BARCODE_ISBNX) { return 1; }
if(symbology == BARCODE_UPCA_CC) { return 1; }
if(symbology == BARCODE_UPCE_CC) { return 1; }
if(symbology == BARCODE_EANX_CC) { return 1; }
return 0;
}
int roundup(float input)
{
float remainder;
int integer_part;
integer_part = (int)input;
remainder = input - integer_part;
if(remainder > 0.1) {
integer_part++;
}
return integer_part;
}
int istwodigits(unsigned char source[], int position)
{
if((source[position] >= '0') && (source[position] <= '9')) {
if((source[position + 1] >= '0') && (source[position + 1] <= '9')) {
return 1;
}
}
return 0;
}
float froundup(float input)
{
float fraction, output = 0.0;
fraction = input - (int)input;
if(fraction > 0.01) { output = (input - fraction) + 1.0; } else { output = input; }
return output;
}
int latin1_process(struct zint_symbol *symbol, unsigned char source[], unsigned char preprocessed[], int *length)
{
int j, i, next;
/* Convert Unicode to Latin-1 for those symbologies which only support Latin-1 */
j = 0;
i = 0;
do {
next = -1;
if(source[i] < 128) {
preprocessed[j] = source[i];
j++;
next = i + 1;
} else {
if(source[i] == 0xC2) {
preprocessed[j] = source[i + 1];
j++;
next = i + 2;
}
if(source[i] == 0xC3) {
preprocessed[j] = source[i + 1] + 64;
j++;
next = i + 2;
}
}
if(next == -1) {
strcpy(symbol->errtxt, "error: Invalid character in input string (only Latin-1 characters supported)");
return ERROR_INVALID_DATA;
}
i = next;
} while(i < *length);
preprocessed[j] = '\0';
*length = j;
return 0;
}
int utf8toutf16(struct zint_symbol *symbol, unsigned char source[], int vals[], int *length)
{
int bpos, jpos, error_number, done;
int next;
bpos = 0;
jpos = 0;
error_number = 0;
next = 0;
do {
done = 0;
if(source[bpos] <= 0x7f) {
/* 1 byte mode (7-bit ASCII) */
vals[jpos] = source[bpos];
next = bpos + 1;
jpos++;
done = 1;
}
if(done == 0) {
if((source[bpos] >= 0x80) && (source[bpos] <= 0xbf)) {
strcpy(symbol->errtxt, "Corrupt Unicode data");
return ERROR_INVALID_DATA;
}
}
if(done == 0) {
if((source[bpos] >= 0xc0) && (source[bpos] <= 0xc1)) {
strcpy(symbol->errtxt, "Overlong encoding not supported");
return ERROR_INVALID_DATA;
}
}
if(done == 0) {
if((source[bpos] >= 0xc2) && (source[bpos] <= 0xdf)) {
/* 2 byte mode */
vals[jpos] = ((source[bpos] & 0x1f) << 6) + (source[bpos + 1] & 0x3f);
next = bpos + 2;
jpos++;
done = 1;
}
}
if(done == 0) {
if((source[bpos] >= 0xe0) && (source[bpos] <= 0xef)) {
/* 3 byte mode */
vals[jpos] = ((source[bpos] & 0x0f) << 12) + ((source[bpos + 1] & 0x3f) << 6) + (source[bpos + 2] & 0x3f);
next = bpos + 3;
jpos ++;
done = 1;
}
}
if(done == 0) {
if(source[bpos] >= 0xf0) {
strcpy(symbol->errtxt, "Unicode sequences of more than 3 bytes not supported");
return ERROR_INVALID_DATA;
}
}
bpos = next;
} while(bpos < *length);
*length = jpos;
return error_number;
}

70
backend/common.h Normal file
View file

@ -0,0 +1,70 @@
/* common.h - Header for all common functions in common.c */
/*
libzint - the open source barcode library
Copyright (C) 2009 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* Used in some logic */
#ifndef __COMMON_H
#define __COMMON_H
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
/* The most commonly used set */
#define NEON "0123456789"
#include "zint.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
extern int ustrlen(unsigned char source[]);
extern void ustrcpy(unsigned char target[], unsigned char source[]);
extern void concat(char dest[], char source[]);
extern void uconcat(unsigned char dest[], unsigned char source[]);
extern int ctoi(char source);
extern char itoc(int source);
extern void to_upper(unsigned char source[]);
extern int is_sane(char test_string[], unsigned char source[], int length);
extern void lookup(char set_string[], char *table[], char data, char dest[]);
extern int posn(char set_string[], char data);
extern void expand(struct zint_symbol *symbol, char data[]);
extern int is_stackable(int symbology);
extern int is_extendable(int symbology);
extern int roundup(float input);
extern int module_is_set(struct zint_symbol *symbol, int y_coord, int x_coord);
extern void set_module(struct zint_symbol *symbol, int y_coord, int x_coord);
extern void unset_module(struct zint_symbol *symbol, int y_coord, int x_coord);
extern int istwodigits(unsigned char source[], int position);
extern float froundup(float input);
extern int parunmodd(unsigned char llyth);
extern int latin1_process(struct zint_symbol *symbol, unsigned char source[], unsigned char preprocessed[], int *length);
extern int utf8toutf16(struct zint_symbol *symbol, unsigned char source[], int vals[], int *length);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __COMMON_H */

1954
backend/composite.c Normal file

File diff suppressed because it is too large Load diff

62
backend/composite.h Normal file
View file

@ -0,0 +1,62 @@
/* composite.c - Tables for UCC.EAN Composite Symbols */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define NUMERIC 110
#define ALPHA 97
#define ISOIEC 105
#define INVALID_CHAR 100
#define ANY_ENC 120
#define ALPHA_OR_ISO 121
/* CC-A component coefficients from ISO/IEC 24728:2006 Annex F */
static int ccaCoeffs[30] = {
/* k = 4 */
522, 568, 723, 809,
/* k = 5 */
427, 919, 460, 155, 566,
/* k = 6 */
861, 285, 19, 803, 17, 766,
/* k = 7 */
76, 925, 537, 597, 784, 691, 437,
/* k = 8 */
237, 308, 436, 284, 646, 653, 428, 379
};
/* rows, error codewords, k-offset of valid CC-A sizes from ISO/IEC 24723:2006 Table 9 */
static int ccaVariants[51] = {
5, 6, 7, 8, 9, 10, 12, 4, 5, 6, 7, 8, 3, 4, 5, 6, 7,
4, 4, 5, 5, 6, 6, 7, 4, 5, 6, 7, 7, 4, 5, 6, 7, 8,
0, 0, 4, 4, 9, 9, 15, 0, 4, 9, 15, 15, 0, 4, 9, 15, 22
};
/* following is Left RAP, Centre RAP, Right RAP and Start Cluster from ISO/IEC 24723:2006 tables 10 and 11 */
static int aRAPTable[68] = {
39, 1, 32, 8, 14, 43, 20, 11, 1, 5, 15, 21, 40, 43, 46, 34, 29,
0, 0, 0, 0, 0, 0, 0, 43, 33, 37, 47, 1, 20, 23, 2, 14, 9,
19, 33, 12, 40, 4, 23, 52, 23, 13, 17, 27, 33, 52, 3, 6, 46, 41,
6, 0, 3, 3, 3, 0, 3, 3, 0, 3, 6, 6, 0, 0, 0, 0, 3
};
/* Row Address Patterns are as defined in pdf417.h */

31
backend/dllversion.c Normal file
View file

@ -0,0 +1,31 @@
/* Sed: http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/programmersguide/versions.asp */
#if defined (_WIN32) && (defined(_USRDLL) || defined(DLL_EXPORT) || defined(PIC))
#include <windows.h>
#include <shlwapi.h>
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) HRESULT DllGetVersion (DLLVERSIONINFO2* pdvi);
#ifdef __cplusplus
}
#endif
HRESULT DllGetVersion (DLLVERSIONINFO2* pdvi)
{
if (!pdvi || (sizeof(*pdvi) != pdvi->info1.cbSize))
return (E_INVALIDARG);
pdvi->info1.dwMajorVersion = 2;
pdvi->info1.dwMinorVersion = 2;
pdvi->info1.dwBuildNumber = 1;
pdvi->info1.dwPlatformID = DLLVER_PLATFORM_WINDOWS;
if (sizeof(DLLVERSIONINFO2) == pdvi->info1.cbSize)
pdvi->ullVersion = MAKEDLLVERULL(2, 2, 1, 0);
return S_OK;
}
#endif /* _WIN32 */

881
backend/dm200.c Normal file
View file

@ -0,0 +1,881 @@
/* dm200.c Handles Data Matrix ECC 200 symbols */
/*
libzint - the open source barcode library
Copyright (C) 2009 Robin Stuart <robin@zint.org.uk>
developed from and including some functions from:
IEC16022 bar code generation
Adrian Kennard, Andrews & Arnold Ltd
with help from Cliff Hones on the RS coding
(c) 2004 Adrian Kennard, Andrews & Arnold Ltd
(c) 2006 Stefan Schmidt <stefan@datenfreihafen.org>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#ifdef _MSC_VER
#include <malloc.h>
#endif
#include "reedsol.h"
#include "common.h"
#include "dm200.h"
// Annex M placement alorithm low level
static void ecc200placementbit(int *array, int NR, int NC, int r, int c, int p, char b)
{
if (r < 0) {
r += NR;
c += 4 - ((NR + 4) % 8);
}
if (c < 0) {
c += NC;
r += 4 - ((NC + 4) % 8);
}
array[r * NC + c] = (p << 3) + b;
}
static void ecc200placementblock(int *array, int NR, int NC, int r,
int c, int p)
{
ecc200placementbit(array, NR, NC, r - 2, c - 2, p, 7);
ecc200placementbit(array, NR, NC, r - 2, c - 1, p, 6);
ecc200placementbit(array, NR, NC, r - 1, c - 2, p, 5);
ecc200placementbit(array, NR, NC, r - 1, c - 1, p, 4);
ecc200placementbit(array, NR, NC, r - 1, c - 0, p, 3);
ecc200placementbit(array, NR, NC, r - 0, c - 2, p, 2);
ecc200placementbit(array, NR, NC, r - 0, c - 1, p, 1);
ecc200placementbit(array, NR, NC, r - 0, c - 0, p, 0);
}
static void ecc200placementcornerA(int *array, int NR, int NC, int p)
{
ecc200placementbit(array, NR, NC, NR - 1, 0, p, 7);
ecc200placementbit(array, NR, NC, NR - 1, 1, p, 6);
ecc200placementbit(array, NR, NC, NR - 1, 2, p, 5);
ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4);
ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3);
ecc200placementbit(array, NR, NC, 1, NC - 1, p, 2);
ecc200placementbit(array, NR, NC, 2, NC - 1, p, 1);
ecc200placementbit(array, NR, NC, 3, NC - 1, p, 0);
}
static void ecc200placementcornerB(int *array, int NR, int NC, int p)
{
ecc200placementbit(array, NR, NC, NR - 3, 0, p, 7);
ecc200placementbit(array, NR, NC, NR - 2, 0, p, 6);
ecc200placementbit(array, NR, NC, NR - 1, 0, p, 5);
ecc200placementbit(array, NR, NC, 0, NC - 4, p, 4);
ecc200placementbit(array, NR, NC, 0, NC - 3, p, 3);
ecc200placementbit(array, NR, NC, 0, NC - 2, p, 2);
ecc200placementbit(array, NR, NC, 0, NC - 1, p, 1);
ecc200placementbit(array, NR, NC, 1, NC - 1, p, 0);
}
static void ecc200placementcornerC(int *array, int NR, int NC, int p)
{
ecc200placementbit(array, NR, NC, NR - 3, 0, p, 7);
ecc200placementbit(array, NR, NC, NR - 2, 0, p, 6);
ecc200placementbit(array, NR, NC, NR - 1, 0, p, 5);
ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4);
ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3);
ecc200placementbit(array, NR, NC, 1, NC - 1, p, 2);
ecc200placementbit(array, NR, NC, 2, NC - 1, p, 1);
ecc200placementbit(array, NR, NC, 3, NC - 1, p, 0);
}
static void ecc200placementcornerD(int *array, int NR, int NC, int p)
{
ecc200placementbit(array, NR, NC, NR - 1, 0, p, 7);
ecc200placementbit(array, NR, NC, NR - 1, NC - 1, p, 6);
ecc200placementbit(array, NR, NC, 0, NC - 3, p, 5);
ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4);
ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3);
ecc200placementbit(array, NR, NC, 1, NC - 3, p, 2);
ecc200placementbit(array, NR, NC, 1, NC - 2, p, 1);
ecc200placementbit(array, NR, NC, 1, NC - 1, p, 0);
}
// Annex M placement alorithm main function
static void ecc200placement(int *array, int NR, int NC)
{
int r, c, p;
// invalidate
for (r = 0; r < NR; r++)
for (c = 0; c < NC; c++)
array[r * NC + c] = 0;
// start
p = 1;
r = 4;
c = 0;
do {
// check corner
if (r == NR && !c)
ecc200placementcornerA(array, NR, NC, p++);
if (r == NR - 2 && !c && NC % 4)
ecc200placementcornerB(array, NR, NC, p++);
if (r == NR - 2 && !c && (NC % 8) == 4)
ecc200placementcornerC(array, NR, NC, p++);
if (r == NR + 4 && c == 2 && !(NC % 8))
ecc200placementcornerD(array, NR, NC, p++);
// up/right
do {
if (r < NR && c >= 0 && !array[r * NC + c])
ecc200placementblock(array, NR, NC, r, c, p++);
r -= 2;
c += 2;
}
while (r >= 0 && c < NC);
r++;
c += 3;
// down/left
do {
if (r >= 0 && c < NC && !array[r * NC + c])
ecc200placementblock(array, NR, NC, r, c, p++);
r += 2;
c -= 2;
}
while (r < NR && c >= 0);
r += 3;
c++;
}
while (r < NR || c < NC);
// unfilled corner
if (!array[NR * NC - 1])
array[NR * NC - 1] = array[NR * NC - NC - 2] = 1;
}
// calculate and append ecc code, and if necessary interleave
static void ecc200(unsigned char *binary, int bytes, int datablock, int rsblock)
{
int blocks = (bytes + 2) / datablock, b;
rs_init_gf(0x12d);
rs_init_code(rsblock, 1);
for (b = 0; b < blocks; b++) {
unsigned char buf[256], ecc[256];
int n, p = 0;
for (n = b; n < bytes; n += blocks)
buf[p++] = binary[n];
rs_encode(p, buf, ecc);
p = rsblock - 1; // comes back reversed
for (n = b; n < rsblock * blocks; n += blocks)
binary[bytes + n] = ecc[p--];
}
rs_free();
}
int isx12(unsigned char source)
{
if(source == 13) { return 1; }
if(source == 42) { return 1; }
if(source == 62) { return 1; }
if(source == 32) { return 1; }
if((source >= '0') && (source <= '9')) { return 1; }
if((source >= 'A') && (source <= 'Z')) { return 1; }
return 0;
}
void dminsert(char binary_string[], int posn, char newbit)
{ /* Insert a character into the middle of a string at position posn */
int i, end;
end = strlen(binary_string);
for(i = end; i > posn; i--) {
binary_string[i] = binary_string[i - 1];
}
binary_string[posn] = newbit;
}
void insert_value(unsigned char binary_stream[], int posn, int streamlen, char newbit)
{
int i;
for(i = streamlen; i > posn; i--) {
binary_stream[i] = binary_stream[i - 1];
}
binary_stream[posn] = newbit;
}
int look_ahead_test(unsigned char source[], int sourcelen, int position, int current_mode, int gs1)
{
/* A custom version of the 'look ahead test' from Annex P */
/* This version is deliberately very reluctant to end a data stream with EDIFACT encoding */
float ascii_count, c40_count, text_count, x12_count, edf_count, b256_count, best_count;
int sp, done, best_scheme;
char reduced_char;
/* step (j) */
if(current_mode == DM_ASCII) {
ascii_count = 0.0;
c40_count = 1.0;
text_count = 1.0;
x12_count = 1.0;
edf_count = 1.0;
b256_count = 1.25;
} else {
ascii_count = 1.0;
c40_count = 2.0;
text_count = 2.0;
x12_count = 2.0;
edf_count = 2.0;
b256_count = 2.25;
}
switch(current_mode) {
case DM_C40: c40_count = 0.0; break;
case DM_TEXT: text_count = 0.0; break;
case DM_X12: x12_count = 0.0; break;
case DM_EDIFACT: edf_count = 0.0; break;
case DM_BASE256: b256_count = 0.0; break;
}
for(sp = position; (sp < sourcelen) && (sp <= (position + 8)); sp++) {
if(source[sp] <= 127) { reduced_char = source[sp]; } else { reduced_char = source[sp] - 127; }
if((source[sp] >= '0') && (source[sp] <= '9')) { ascii_count += 0.5; } else { ascii_count += 1.0; }
if(source[sp] > 127) { ascii_count += 1.0; }
done = 0;
if(reduced_char == ' ') { c40_count += (2.0 / 3.0); done = 1; }
if((reduced_char >= '0') && (reduced_char <= '9')) { c40_count += (2.0 / 3.0); done = 1; }
if((reduced_char >= 'A') && (reduced_char <= 'Z')) { c40_count += (2.0 / 3.0); done = 1; }
if(source[sp] > 127) { c40_count += (4.0 / 3.0); }
if(done == 0) { c40_count += (4.0 / 3.0); }
done = 0;
if(reduced_char == ' ') { text_count += (2.0 / 3.0); done = 1; }
if((reduced_char >= '0') && (reduced_char <= '9')) { text_count += (2.0 / 3.0); done = 1; }
if((reduced_char >= 'a') && (reduced_char <= 'z')) { text_count += (2.0 / 3.0); done = 1; }
if(source[sp] > 127) { text_count += (4.0 / 3.0); }
if(done == 0) { text_count += (4.0 / 3.0); }
if(isx12(source[sp])) { x12_count += (2.0 / 3.0); } else { x12_count += 4.0; }
/* step (p) */
done = 0;
if((source[sp] >= ' ') && (source[sp] <= '^')) { edf_count += (3.0 / 4.0); } else { edf_count += 6.0; }
if(gs1 && (source[sp] == '[')) { edf_count += 6.0; }
if(sp >= (sourcelen - 5)) { edf_count += 6.0; } /* MMmmm fudge! */
/* step (q) */
if(gs1 && (source[sp] == '[')) { b256_count += 4.0; } else { b256_count += 1.0; }
/* printf("%c lat a%.2f c%.2f t%.2f x%.2f e%.2f b%.2f\n", source[sp], ascii_count, c40_count, text_count, x12_count, edf_count, b256_count); */
}
best_count = ascii_count;
best_scheme = DM_ASCII;
if(b256_count <= best_count) {
best_count = b256_count;
best_scheme = DM_BASE256;
}
if(edf_count <= best_count) {
best_count = edf_count;
best_scheme = DM_EDIFACT;
}
if(text_count <= best_count) {
best_count = text_count;
best_scheme = DM_TEXT;
}
if(x12_count <= best_count) {
best_count = x12_count;
best_scheme = DM_X12;
}
if(c40_count <= best_count) {
best_count = c40_count;
best_scheme = DM_C40;
}
return best_scheme;
}
int dm200encode(struct zint_symbol *symbol, unsigned char source[], unsigned char target[], int *last_mode, int length)
{
/* Encodes data using ASCII, C40, Text, X12, EDIFACT or Base 256 modes as appropriate */
/* Supports encoding FNC1 in supporting systems */
int sp, tp, i, gs1;
int current_mode, next_mode;
int inputlen = length;
int c40_buffer[6], c40_p;
int text_buffer[6], text_p;
int x12_buffer[6], x12_p;
int edifact_buffer[8], edifact_p;
int debug = 0;
#ifndef _MSC_VER
char binary[2 * inputlen];
#else
char* binary = (char*)_alloca(2 * inputlen);
#endif
sp = 0;
tp = 0;
memset(c40_buffer, 0, 6);
c40_p = 0;
memset(text_buffer, 0, 6);
text_p = 0;
memset(x12_buffer, 0, 6);
x12_p = 0;
memset(edifact_buffer, 0, 8);
edifact_p = 0;
strcpy(binary, "");
/* step (a) */
current_mode = DM_ASCII;
next_mode = DM_ASCII;
if(symbol->input_mode == GS1_MODE) { gs1 = 1; } else { gs1 = 0; }
if(gs1) {
target[tp] = 232; tp++;
concat(binary, " ");
if(debug) printf("FN1 ");
} /* FNC1 */
if(symbol->output_options & READER_INIT) {
if(gs1) {
strcpy(symbol->errtxt, "Cannot encode in GS1 mode and Reader Initialisation at the same time");
return ERROR_INVALID_OPTION;
} else {
target[tp] = 234; tp++; /* Reader Programming */
concat(binary, " ");
if(debug) printf("RP ");
}
}
while (sp < inputlen) {
current_mode = next_mode;
/* step (b) - ASCII encodation */
if(current_mode == DM_ASCII) {
next_mode = DM_ASCII;
if(istwodigits(source, sp) && ((sp + 1) != inputlen)) {
target[tp] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130;
if(debug) printf("N%d ", target[tp] - 130);
tp++; concat(binary, " ");
sp += 2;
} else {
next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);
if(next_mode != DM_ASCII) {
switch(next_mode) {
case DM_C40: target[tp] = 230; tp++; concat(binary, " ");
if(debug) printf("C40 "); break;
case DM_TEXT: target[tp] = 239; tp++; concat(binary, " ");
if(debug) printf("TEX "); break;
case DM_X12: target[tp] = 238; tp++; concat(binary, " ");
if(debug) printf("X12 "); break;
case DM_EDIFACT: target[tp] = 240; tp++; concat(binary, " ");
if(debug) printf("EDI "); break;
case DM_BASE256: target[tp] = 231; tp++; concat(binary, " ");
if(debug) printf("BAS "); break;
}
} else {
if(source[sp] > 127) {
target[tp] = 235; /* FNC4 */
if(debug) printf("FN4 ");
tp++;
target[tp] = (source[sp] - 128) + 1;
if(debug) printf("A%02X ", target[tp] - 1);
tp++; concat(binary, " ");
} else {
if(gs1 && (source[sp] == '[')) {
target[tp] = 232; /* FNC1 */
if(debug) printf("FN1 ");
} else {
target[tp] = source[sp] + 1;
if(debug) printf("A%02X ", target[tp] - 1);
}
tp++;
concat(binary, " ");
}
sp++;
}
}
}
/* step (c) C40 encodation */
if(current_mode == DM_C40) {
int shift_set, value;
next_mode = DM_C40;
if(c40_p == 0) {
next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);
}
if(next_mode != DM_C40) {
target[tp] = 254; tp++; concat(binary, " ");/* Unlatch */
next_mode = DM_ASCII;
if (debug) printf("ASC ");
} else {
if(source[sp] > 127) {
c40_buffer[c40_p] = 1; c40_p++;
c40_buffer[c40_p] = 30; c40_p++; /* Upper Shift */
shift_set = c40_shift[source[sp] - 128];
value = c40_value[source[sp] - 128];
} else {
shift_set = c40_shift[source[sp]];
value = c40_value[source[sp]];
}
if(gs1 && (source[sp] == '[')) {
shift_set = 2;
value = 27; /* FNC1 */
}
if(shift_set != 0) {
c40_buffer[c40_p] = shift_set - 1; c40_p++;
}
c40_buffer[c40_p] = value; c40_p++;
if(c40_p >= 3) {
int iv;
iv = (1600 * c40_buffer[0]) + (40 * c40_buffer[1]) + (c40_buffer[2]) + 1;
target[tp] = iv / 256; tp++;
target[tp] = iv % 256; tp++;
concat(binary, " ");
if (debug) printf("[%d %d %d] ", c40_buffer[0], c40_buffer[1], c40_buffer[2]);
c40_buffer[0] = c40_buffer[3];
c40_buffer[1] = c40_buffer[4];
c40_buffer[2] = c40_buffer[5];
c40_buffer[3] = 0;
c40_buffer[4] = 0;
c40_buffer[5] = 0;
c40_p -= 3;
}
sp++;
}
}
/* step (d) Text encodation */
if(current_mode == DM_TEXT) {
int shift_set, value;
next_mode = DM_TEXT;
if(text_p == 0) {
next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);
}
if(next_mode != DM_TEXT) {
target[tp] = 254; tp++; concat(binary, " ");/* Unlatch */
next_mode = DM_ASCII;
if (debug) printf("ASC ");
} else {
if(source[sp] > 127) {
text_buffer[text_p] = 1; text_p++;
text_buffer[text_p] = 30; text_p++; /* Upper Shift */
shift_set = text_shift[source[sp] - 128];
value = text_value[source[sp] - 128];
} else {
shift_set = text_shift[source[sp]];
value = text_value[source[sp]];
}
if(gs1 && (source[sp] == '[')) {
shift_set = 2;
value = 27; /* FNC1 */
}
if(shift_set != 0) {
text_buffer[text_p] = shift_set - 1; text_p++;
}
text_buffer[text_p] = value; text_p++;
if(text_p >= 3) {
int iv;
iv = (1600 * text_buffer[0]) + (40 * text_buffer[1]) + (text_buffer[2]) + 1;
target[tp] = iv / 256; tp++;
target[tp] = iv % 256; tp++;
concat(binary, " ");
if (debug) printf("[%d %d %d] ", text_buffer[0], text_buffer[1], text_buffer[2]);
text_buffer[0] = text_buffer[3];
text_buffer[1] = text_buffer[4];
text_buffer[2] = text_buffer[5];
text_buffer[3] = 0;
text_buffer[4] = 0;
text_buffer[5] = 0;
text_p -= 3;
}
sp++;
}
}
/* step (e) X12 encodation */
if(current_mode == DM_X12) {
int value = 0;
next_mode = DM_X12;
if(text_p == 0) {
next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);
}
if(next_mode != DM_X12) {
target[tp] = 254; tp++; concat(binary, " ");/* Unlatch */
next_mode = DM_ASCII;
if (debug) printf("ASC ");
} else {
if(source[sp] == 13) { value = 0; }
if(source[sp] == '*') { value = 1; }
if(source[sp] == '>') { value = 2; }
if(source[sp] == ' ') { value = 3; }
if((source[sp] >= '0') && (source[sp] <= '9')) { value = (source[sp] - '0') + 4; }
if((source[sp] >= 'A') && (source[sp] <= 'Z')) { value = (source[sp] - 'A') + 14; }
x12_buffer[x12_p] = value; x12_p++;
if(x12_p >= 3) {
int iv;
iv = (1600 * x12_buffer[0]) + (40 * x12_buffer[1]) + (x12_buffer[2]) + 1;
target[tp] = iv / 256; tp++;
target[tp] = iv % 256; tp++;
concat(binary, " ");
if (debug) printf("[%d %d %d] ", x12_buffer[0], x12_buffer[1], x12_buffer[2]);
x12_buffer[0] = x12_buffer[3];
x12_buffer[1] = x12_buffer[4];
x12_buffer[2] = x12_buffer[5];
x12_buffer[3] = 0;
x12_buffer[4] = 0;
x12_buffer[5] = 0;
x12_p -= 3;
}
sp++;
}
}
/* step (f) EDIFACT encodation */
if(current_mode == DM_EDIFACT) {
int value = 0;
next_mode = DM_EDIFACT;
if(edifact_p == 3) {
next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);
}
if(next_mode != DM_EDIFACT) {
edifact_buffer[edifact_p] = 31; edifact_p++;
next_mode = DM_ASCII;
} else {
if((source[sp] >= '@') && (source[sp] <= '^')) { value = source[sp] - '@'; }
if((source[sp] >= ' ') && (source[sp] <= '?')) { value = source[sp]; }
edifact_buffer[edifact_p] = value; edifact_p++;
sp++;
}
if(edifact_p >= 4) {
target[tp] = (edifact_buffer[0] << 2) + ((edifact_buffer[1] & 0x30) >> 4); tp++;
target[tp] = ((edifact_buffer[1] & 0x0f) << 4) + ((edifact_buffer[2] & 0x3c) >> 2); tp++;
target[tp] = ((edifact_buffer[2] & 0x03) << 6) + edifact_buffer[3]; tp++;
concat(binary, " ");
if (debug) printf("[%d %d %d %d] ", edifact_buffer[0], edifact_buffer[1], edifact_buffer[2], edifact_buffer[3]);
edifact_buffer[0] = edifact_buffer[4];
edifact_buffer[1] = edifact_buffer[5];
edifact_buffer[2] = edifact_buffer[6];
edifact_buffer[3] = edifact_buffer[7];
edifact_buffer[4] = 0;
edifact_buffer[5] = 0;
edifact_buffer[6] = 0;
edifact_buffer[7] = 0;
edifact_p -= 4;
}
}
/* step (g) Base 256 encodation */
if(current_mode == DM_BASE256) {
next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);
if(next_mode == DM_BASE256) {
target[tp] = source[sp];
if(debug) printf("B%02X ", target[tp]);
tp++;
sp++;
concat(binary, "b");
} else {
next_mode = DM_ASCII;
if(debug) printf("ASC ");
}
}
if(tp > 1558) {
return 0;
}
} /* while */
/* Empty buffers */
if(c40_p == 2) {
target[tp] = 254; tp++; /* unlatch */
target[tp] = source[inputlen - 2] + 1; tp++;
target[tp] = source[inputlen - 1] + 1; tp++;
concat(binary, " ");
if(debug) printf("ASC A%02X A%02X ", target[tp - 2] - 1, target[tp - 1] - 1);
current_mode = DM_ASCII;
}
if(c40_p == 1) {
target[tp] = 254; tp++; /* unlatch */
target[tp] = source[inputlen - 1] + 1; tp++;
concat(binary, " ");
if(debug) printf("ASC A%02X ", target[tp - 1] - 1);
current_mode = DM_ASCII;
}
if(text_p == 2) {
target[tp] = 254; tp++; /* unlatch */
target[tp] = source[inputlen - 2] + 1; tp++;
target[tp] = source[inputlen - 1] + 1; tp++;
concat(binary, " ");
if(debug) printf("ASC A%02X A%02X ", target[tp - 2] - 1, target[tp - 1] - 1);
current_mode = DM_ASCII;
}
if(text_p == 1) {
target[tp] = 254; tp++; /* unlatch */
target[tp] = source[inputlen - 1] + 1; tp++;
concat(binary, " ");
if(debug) printf("ASC A%02X ", target[tp - 1] - 1);
current_mode = DM_ASCII;
}
if(x12_p == 2) {
target[tp] = 254; tp++; /* unlatch */
target[tp] = source[inputlen - 2] + 1; tp++;
target[tp] = source[inputlen - 1] + 1; tp++;
concat(binary, " ");
if(debug) printf("ASC A%02X A%02X ", target[tp - 2] - 1, target[tp - 1] - 1);
current_mode = DM_ASCII;
}
if(x12_p == 1) {
target[tp] = 254; tp++; /* unlatch */
target[tp] = source[inputlen - 1] + 1; tp++;
concat(binary, " ");
if(debug) printf("ASC A%02X ", target[tp - 1] - 1);
current_mode = DM_ASCII;
}
/* Add length and randomising algorithm to b256 */
i = 0;
while (i < tp) {
if(binary[i] == 'b') {
if((i == 0) || ((i != 0) && (binary[i - 1] != 'b'))) {
/* start of binary data */
int binary_count; /* length of b256 data */
for(binary_count = 0; binary[binary_count + i] == 'b'; binary_count++);
if(binary_count <= 249) {
dminsert(binary, i, 'b');
insert_value(target, i, tp, binary_count); tp++;
} else {
dminsert(binary, i, 'b');
dminsert(binary, i + 1, 'b');
insert_value(target, i, tp, (binary_count / 250) + 249); tp++;
insert_value(target, i + 1, tp, binary_count % 250); tp++;
}
}
}
i++;
}
for(i = 0; i < tp; i++) {
if(binary[i] == 'b') {
int prn, temp;
prn = ((149 * (i + 1)) % 255) + 1;
temp = target[i] + prn;
if (temp <= 255) { target[i] = temp; } else { target[i] = temp - 256; }
}
}
if(debug) {
printf("\n\n");
for(i = 0; i < tp; i++){
printf("%02X ", target[i]);
}
printf("\n");
}
*(last_mode) = current_mode;
return tp;
}
void add_tail(unsigned char target[], int tp, int tail_length, int last_mode)
{
/* adds unlatch and pad bits */
int i, prn, temp;
switch(last_mode) {
case DM_C40:
case DM_TEXT:
case DM_X12:
target[tp] = 254; tp++; /* Unlatch */
tail_length--;
}
for(i = tail_length; i > 0; i--) {
if(i == tail_length) {
target[tp] = 129; tp++; /* Pad */
} else {
prn = ((149 * (tp + 1)) % 253) + 1;
temp = 129 + prn;
if(temp <= 254) {
target[tp] = temp; tp++;
} else {
target[tp] = temp - 254; tp++;
}
}
}
}
int data_matrix_200(struct zint_symbol *symbol, unsigned char source[], int length)
{
int inputlen, i;
unsigned char binary[2000];
int binlen;
int symbolsize, optionsize, calcsize;
int taillength, error_number = 0;
int H, W, FH, FW, datablock, bytes, rsblock;
int last_mode;
unsigned char *grid = 0;
inputlen = length;
binlen = dm200encode(symbol, source, binary, &last_mode, length);
if(binlen == 0) {
strcpy(symbol->errtxt, "Data too long to fit in symbol");
return ERROR_TOO_LONG;
}
if((symbol->option_2 >= 1) && (symbol->option_2 <= 30)) {
optionsize = intsymbol[symbol->option_2 - 1];
} else {
optionsize = -1;
}
calcsize = 29;
for(i = 29; i > -1; i--) {
if(matrixbytes[i] > binlen) {
calcsize = i;
}
}
if(symbol->option_3 == DM_SQUARE) {
/* Force to use square symbol */
switch(calcsize) {
case 2:
case 4:
case 6:
case 9:
case 11:
case 14:
calcsize++;
}
}
symbolsize = optionsize;
if(calcsize > optionsize) {
symbolsize = calcsize;
if(optionsize != -1) {
/* flag an error */
error_number = WARN_INVALID_OPTION;
strcpy(symbol->errtxt, "Data does not fit in selected symbol size");
}
}
H = matrixH[symbolsize];
W = matrixW[symbolsize];
FH = matrixFH[symbolsize];
FW = matrixFW[symbolsize];
bytes = matrixbytes[symbolsize];
datablock = matrixdatablock[symbolsize];
rsblock = matrixrsblock[symbolsize];
taillength = bytes - binlen;
if(taillength != 0) {
add_tail(binary, binlen, taillength, last_mode);
}
// ecc code
ecc200(binary, bytes, datablock, rsblock);
{ // placement
int x, y, NC, NR, *places;
NC = W - 2 * (W / FW);
NR = H - 2 * (H / FH);
places = (int*)malloc(NC * NR * sizeof(int));
ecc200placement(places, NR, NC);
grid = (unsigned char*)malloc(W * H);
memset(grid, 0, W * H);
for (y = 0; y < H; y += FH) {
for (x = 0; x < W; x++)
grid[y * W + x] = 1;
for (x = 0; x < W; x += 2)
grid[(y + FH - 1) * W + x] = 1;
}
for (x = 0; x < W; x += FW) {
for (y = 0; y < H; y++)
grid[y * W + x] = 1;
for (y = 0; y < H; y += 2)
grid[y * W + x + FW - 1] = 1;
}
for (y = 0; y < NR; y++) {
for (x = 0; x < NC; x++) {
int v = places[(NR - y - 1) * NC + x];
//fprintf (stderr, "%4d", v);
if (v == 1 || (v > 7 && (binary[(v >> 3) - 1] & (1 << (v & 7)))))
grid[(1 + y + 2 * (y / (FH - 2))) * W + 1 + x + 2 * (x / (FW - 2))] = 1;
}
//fprintf (stderr, "\n");
}
for(y = H - 1; y >= 0; y--) {
int x;
for(x = 0; x < W; x++) {
if(grid[W * y + x]) {
set_module(symbol, (H - y) - 1, x);
}
}
symbol->row_height[(H - y) - 1] = 1;
}
free(grid);
free(places);
}
symbol->rows = H;
symbol->width = W;
return error_number;
}

101
backend/dm200.h Normal file
View file

@ -0,0 +1,101 @@
/* dm200.h - Handles Data Matrix ECC 200 */
/*
libzint - the open source barcode library
Copyright (C) 2009 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "common.h"
#ifndef __IEC16022ECC200_H
#define __IEC16022ECC200_H
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
extern int data_matrix_200(struct zint_symbol *symbol, unsigned char source[], int length);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define MAXBARCODE 3116
#define DM_ASCII 1
#define DM_C40 2
#define DM_TEXT 3
#define DM_X12 4
#define DM_EDIFACT 5
#define DM_BASE256 6
static int c40_shift[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };
static int c40_value[] = {
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
3,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,4,5,6,7,8,9,10,11,12,13,
15,16,17,18,19,20,21,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,
22,23,24,25,26,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 };
static int text_shift[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3 };
static int text_value[] = {
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
3,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,4,5,6,7,8,9,10,11,12,13,
15,16,17,18,19,20,21,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,
22,23,24,25,26,0,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,27,28,29,30,31 };
static int intsymbol[] = {
0,1,3,5,7,8,10,12,13,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,2,4,6,9,11,14 };
static int matrixH[] = {
10, 12, 8, 14, 8, 16, 12, 18, 20, 12, 22, 16, 24, 26, 16, 32, 36, 40, 44, 48,
52, 64, 72, 80, 88, 96, 104, 120, 132, 144 };
static int matrixW[] = {
10, 12, 18, 14, 32, 16, 26, 18, 20, 36, 22, 36, 24, 26, 48, 32, 36, 40, 44,
48, 52, 64, 72, 80, 88, 96, 104, 120, 132, 144 };
static int matrixFH[] = {
10, 12, 8, 14, 8, 16, 12, 18, 20, 12, 22, 16, 24, 26, 16, 16, 18, 20, 22, 24,
26, 16, 18, 20, 22, 24, 26, 20, 22, 24 };
static int matrixFW[] = {
10, 12, 18, 14, 16, 16, 26, 18, 20, 18, 22, 18, 24, 26, 24, 16, 18, 20, 22,
24, 26, 16, 18, 20, 22, 24, 26, 20, 22, 24 };
static int matrixbytes[] = {
3, 5, 5, 8, 10, 12, 16, 18, 22, 22, 30, 32, 36, 44, 49, 62, 86, 114, 144,
174, 204, 280, 368, 456, 576, 696, 816, 1050, 1304, 1558 };
static int matrixdatablock[] = {
3, 5, 5, 8, 10, 12, 16, 18, 22, 22, 30, 32, 36, 44, 49, 62, 86, 114, 144,
174, 102, 140, 92, 114, 144, 174, 136, 175, 163, 156 };
static int matrixrsblock[] = {
5, 7, 7, 10, 11, 12, 14, 14, 18, 18, 20, 24, 24, 28, 28, 36, 42, 48, 56, 68,
42, 56, 36, 48, 56, 68, 56, 68, 62, 62 };
#endif /* __IEC16022ECC200_H */

1318
backend/dmatrix.c Normal file

File diff suppressed because it is too large Load diff

671
backend/dmatrix.h Normal file
View file

@ -0,0 +1,671 @@
/* dmatrix.h - Data Matrix ECC 000 - 150 tables */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* Data taken from ISO/IEC 16022:2006 Annex H "ECC 000 - 140 data module placement grids" */
int tableh1[] = { /* 7 x 7 data */
2,45,10,38,24,21,1,
12,40,26,5,33,19,47,
22,31,29,15,43,8,36,
34,20,48,13,41,27,6,
44,9,37,23,17,30,16,
39,25,4,32,18,46,11,
0,28,14,42,7,35,3
};
int tableh2[] = { /* 9 x 9 data */
2,19,55,10,46,28,64,73,1,
62,17,53,35,71,8,80,44,26,
49,31,67,4,76,40,22,58,13,
69,6,78,42,24,60,15,51,33,
74,38,20,56,11,47,29,65,37,
25,61,16,52,34,70,7,79,43,
12,48,30,66,63,75,39,21,57,
32,68,5,77,41,23,59,14,50,
0,72,36,18,54,9,45,27,3
};
int tableh3[] = { /* 11 x 11 data */
2,26,114,70,15,103,59,37,81,4,1,
117,73,18,106,62,40,84,7,95,51,29,
12,100,56,34,78,92,89,45,23,111,67,
65,43,87,10,98,54,32,120,76,21,109,
82,5,93,49,27,115,71,16,104,60,38,
96,52,30,118,74,19,107,63,41,85,8,
24,112,68,13,101,57,35,79,48,90,46,
75,20,108,64,42,86,9,97,53,31,119,
102,58,36,80,77,91,47,25,113,69,14,
39,83,6,94,50,28,116,72,17,105,61,
0,88,44,22,110,66,11,99,55,33,3
};
int tableh4[] = { /* 13 x 13 data */
2,159,29,133,81,16,120,68,42,146,94,91,1,
37,141,89,24,128,76,50,154,102,11,115,63,167,
83,18,122,70,44,148,96,5,109,57,161,31,135,
125,73,47,151,99,8,112,60,164,34,138,86,21,
40,144,92,107,105,53,157,27,131,79,14,118,66,
103,12,116,64,168,38,142,90,25,129,77,51,155,
110,58,162,32,136,84,19,123,71,45,149,97,6,
165,35,139,87,22,126,74,48,152,100,9,113,61,
132,80,15,119,67,41,145,93,55,106,54,158,28,
23,127,75,49,153,101,10,114,62,166,36,140,88,
69,43,147,95,4,108,56,160,30,134,82,17,121,
150,98,7,111,59,163,33,137,85,20,124,72,46,
0,104,52,156,26,130,78,13,117,65,39,143,3
};
int tableh5[] = { /* 15 x 15 data */
2,187,37,157,97,217,22,142,82,202,52,172,112,7,1,
41,161,101,221,26,146,86,206,56,176,116,11,131,71,191,
93,213,18,138,78,198,48,168,108,105,123,63,183,33,153,
28,148,88,208,58,178,118,13,133,73,193,43,163,103,223,
80,200,50,170,110,5,125,65,185,35,155,95,215,20,140,
54,174,114,9,129,69,189,39,159,99,219,24,144,84,204,
106,127,121,61,181,31,151,91,211,16,136,76,196,46,166,
134,74,194,44,164,104,224,29,149,89,209,59,179,119,14,
186,36,156,96,216,21,141,81,201,51,171,111,6,126,66,
160,100,220,25,145,85,205,55,175,115,10,130,70,190,40,
212,17,137,77,197,47,167,107,67,122,62,182,32,152,92,
147,87,207,57,177,117,12,132,72,192,42,162,102,222,27,
199,49,169,109,4,124,64,184,34,154,94,214,19,139,79,
173,113,8,128,68,188,38,158,98,218,23,143,83,203,53,
0,120,60,180,30,150,90,210,15,135,75,195,45,165,3
};
int tableh6[] = { /* 17 x 17 data */
2,69,205,35,171,103,239,18,154,86,222,52,188,120,256,273,1,
220,50,186,118,254,33,169,101,237,67,203,135,271,16,288,152,84,
178,110,246,25,161,93,229,59,195,127,263,8,280,144,76,212,42,
250,29,165,97,233,63,199,131,267,12,284,148,80,216,46,182,114,
157,89,225,55,191,123,259,4,276,140,72,208,38,174,106,242,21,
235,65,201,133,269,14,286,150,82,218,48,184,116,252,31,167,99,
193,125,261,6,278,142,74,210,40,176,108,244,23,159,91,227,57,
265,10,282,146,78,214,44,180,112,248,27,163,95,231,61,197,129,
274,138,70,206,36,172,104,240,19,155,87,223,53,189,121,257,137,
83,219,49,185,117,253,32,168,100,236,66,202,134,270,15,287,151,
41,177,109,245,24,160,92,228,58,194,126,262,7,279,143,75,211,
113,249,28,164,96,232,62,198,130,266,11,283,147,79,215,45,181,
20,156,88,224,54,190,122,258,255,275,139,71,207,37,173,105,241,
98,234,64,200,132,268,13,285,149,81,217,47,183,115,251,30,166,
56,192,124,260,5,277,141,73,209,39,175,107,243,22,158,90,226,
128,264,9,281,145,77,213,43,179,111,247,26,162,94,230,60,196,
0,272,136,68,204,34,170,102,238,17,153,85,221,51,187,119,3
};
int tableh7[] = { /* 19 x 19 data */
2,82,234,44,348,196,120,272,25,329,177,101,253,63,215,139,291,6,1,
239,49,353,201,125,277,30,334,182,106,258,68,220,144,296,11,315,163,87,
343,191,115,267,20,324,172,96,248,58,210,134,286,310,305,153,77,229,39,
132,284,37,341,189,113,265,75,227,151,303,18,322,170,94,246,56,360,208,
28,332,180,104,256,66,218,142,294,9,313,161,85,237,47,351,199,123,275,
185,109,261,71,223,147,299,14,318,166,90,242,52,356,204,128,280,33,337,
251,61,213,137,289,4,308,156,80,232,42,346,194,118,270,23,327,175,99,
225,149,301,16,320,168,92,244,54,358,206,130,282,35,339,187,111,263,73,
292,7,311,159,83,235,45,349,197,121,273,26,330,178,102,254,64,216,140,
316,164,88,240,50,354,202,126,278,31,335,183,107,259,69,221,145,297,12,
78,230,40,344,192,116,268,21,325,173,97,249,59,211,135,287,158,306,154,
55,359,207,131,283,36,340,188,112,264,74,226,150,302,17,321,169,93,245,
198,122,274,27,331,179,103,255,65,217,141,293,8,312,160,84,236,46,350,
279,32,336,184,108,260,70,222,146,298,13,317,165,89,241,51,355,203,127,
326,174,98,250,60,212,136,288,285,307,155,79,231,41,345,193,117,269,22,
110,262,72,224,148,300,15,319,167,91,243,53,357,205,129,281,34,338,186,
62,214,138,290,5,309,157,81,233,43,347,195,119,271,24,328,176,100,252,
143,295,10,314,162,86,238,48,352,200,124,276,29,333,181,105,257,67,219,
0,304,152,76,228,38,342,190,114,266,19,323,171,95,247,57,209,133,3
};
int tableh8[] = { /* 21 x 21 data */
2,88,424,256,46,382,214,130,298,25,361,193,109,277,67,403,235,151,319,4,1,
437,269,59,395,227,143,311,38,374,206,122,290,80,416,248,164,332,17,353,185,101,
49,385,217,133,301,28,364,196,112,280,70,406,238,154,322,7,343,175,91,427,259,
222,138,306,33,369,201,117,285,75,411,243,159,327,12,348,180,96,432,264,54,390,
295,22,358,190,106,274,64,400,232,148,316,340,337,169,85,421,253,43,379,211,127,
377,209,125,293,83,419,251,167,335,20,356,188,104,440,272,62,398,230,146,314,41,
115,283,73,409,241,157,325,10,346,178,94,430,262,52,388,220,136,304,31,367,199,
78,414,246,162,330,15,351,183,99,435,267,57,393,225,141,309,36,372,204,120,288,
236,152,320,5,341,173,89,425,257,47,383,215,131,299,26,362,194,110,278,68,404,
333,18,354,186,102,438,270,60,396,228,144,312,39,375,207,123,291,81,417,249,165,
344,176,92,428,260,50,386,218,134,302,29,365,197,113,281,71,407,239,155,323,8,
97,433,265,55,391,223,139,307,34,370,202,118,286,76,412,244,160,328,13,349,181,
254,44,380,212,128,296,23,359,191,107,275,65,401,233,149,317,172,338,170,86,422,
397,229,145,313,40,376,208,124,292,82,418,250,166,334,19,355,187,103,439,271,61,
135,303,30,366,198,114,282,72,408,240,156,324,9,345,177,93,429,261,51,387,219,
35,371,203,119,287,77,413,245,161,329,14,350,182,98,434,266,56,392,224,140,308,
192,108,276,66,402,234,150,318,315,339,171,87,423,255,45,381,213,129,297,24,360,
289,79,415,247,163,331,16,352,184,100,436,268,58,394,226,142,310,37,373,205,121,
405,237,153,321,6,342,174,90,426,258,48,384,216,132,300,27,363,195,111,279,69,
158,326,11,347,179,95,431,263,53,389,221,137,305,32,368,200,116,284,74,410,242,
0,336,168,84,420,252,42,378,210,126,294,21,357,189,105,273,63,399,231,147,3
};
int tableh9[] = { /* 23 x 23 data */
2,102,470,286,56,424,240,148,516,332,33,401,217,125,493,309,79,447,263,171,355,10,1,
476,292,62,430,246,154,522,338,39,407,223,131,499,315,85,453,269,177,361,16,384,200,108,
50,418,234,142,510,326,27,395,211,119,487,303,73,441,257,165,349,4,372,188,96,464,280,
249,157,525,341,42,410,226,134,502,318,88,456,272,180,364,19,387,203,111,479,295,65,433,
513,329,30,398,214,122,490,306,76,444,260,168,352,7,375,191,99,467,283,53,421,237,145,
36,404,220,128,496,312,82,450,266,174,358,13,381,197,105,473,289,59,427,243,151,519,335,
208,116,484,300,70,438,254,162,346,378,369,185,93,461,277,47,415,231,139,507,323,24,392,
505,321,91,459,275,183,367,22,390,206,114,482,298,68,436,252,160,528,344,45,413,229,137,
80,448,264,172,356,11,379,195,103,471,287,57,425,241,149,517,333,34,402,218,126,494,310,
270,178,362,17,385,201,109,477,293,63,431,247,155,523,339,40,408,224,132,500,316,86,454,
350,5,373,189,97,465,281,51,419,235,143,511,327,28,396,212,120,488,304,74,442,258,166,
388,204,112,480,296,66,434,250,158,526,342,43,411,227,135,503,319,89,457,273,181,365,20,
100,468,284,54,422,238,146,514,330,31,399,215,123,491,307,77,445,261,169,353,8,376,192,
290,60,428,244,152,520,336,37,405,221,129,497,313,83,451,267,175,359,14,382,198,106,474,
416,232,140,508,324,25,393,209,117,485,301,71,439,255,163,347,194,370,186,94,462,278,48,
159,527,343,44,412,228,136,504,320,90,458,274,182,366,21,389,205,113,481,297,67,435,251,
331,32,400,216,124,492,308,78,446,262,170,354,9,377,193,101,469,285,55,423,239,147,515,
406,222,130,498,314,84,452,268,176,360,15,383,199,107,475,291,61,429,245,153,521,337,38,
118,486,302,72,440,256,164,348,345,371,187,95,463,279,49,417,233,141,509,325,26,394,210,
317,87,455,271,179,363,18,386,202,110,478,294,64,432,248,156,524,340,41,409,225,133,501,
443,259,167,351,6,374,190,98,466,282,52,420,236,144,512,328,29,397,213,121,489,305,75,
173,357,12,380,196,104,472,288,58,426,242,150,518,334,35,403,219,127,495,311,81,449,265,
0,368,184,92,460,276,46,414,230,138,506,322,23,391,207,115,483,299,69,437,253,161,3
};
int tableh10[] = { /* 25 x 25 data */
2,603,103,503,303,53,453,253,153,553,353,28,428,228,128,528,328,78,478,278,178,578,378,375,1,
123,523,323,73,473,273,173,573,373,48,448,248,148,548,348,98,498,298,198,598,398,23,423,223,623,
311,61,461,261,161,561,361,36,436,236,136,536,336,86,486,286,186,586,386,11,411,211,611,111,511,
467,267,167,567,367,42,442,242,142,542,342,92,492,292,192,592,392,17,417,217,617,117,517,317,67,
155,555,355,30,430,230,130,530,330,80,480,280,180,580,380,5,405,205,605,105,505,305,55,455,255,
370,45,445,245,145,545,345,95,495,295,195,595,395,20,420,220,620,120,520,320,70,470,270,170,570,
433,233,133,533,333,83,483,283,183,583,383,8,408,208,608,108,508,308,58,458,258,158,558,358,33,
139,539,339,89,489,289,189,589,389,14,414,214,614,114,514,314,64,464,264,164,564,364,39,439,239,
326,76,476,276,176,576,376,403,401,201,601,101,501,301,51,451,251,151,551,351,26,426,226,126,526,
499,299,199,599,399,24,424,224,624,124,524,324,74,474,274,174,574,374,49,449,249,149,549,349,99,
187,587,387,12,412,212,612,112,512,312,62,462,262,162,562,362,37,437,237,137,537,337,87,487,287,
393,18,418,218,618,118,518,318,68,468,268,168,568,368,43,443,243,143,543,343,93,493,293,193,593,
406,206,606,106,506,306,56,456,256,156,556,356,31,431,231,131,531,331,81,481,281,181,581,381,6,
621,121,521,321,71,471,271,171,571,371,46,446,246,146,546,346,96,496,296,196,596,396,21,421,221,
509,309,59,459,259,159,559,359,34,434,234,134,534,334,84,484,284,184,584,384,9,409,209,609,109,
65,465,265,165,565,365,40,440,240,140,540,340,90,490,290,190,590,390,15,415,215,615,115,515,315,
252,152,552,352,27,427,227,127,527,327,77,477,277,177,577,377,203,402,202,602,102,502,302,52,452,
572,372,47,447,247,147,547,347,97,497,297,197,597,397,22,422,222,622,122,522,322,72,472,272,172,
35,435,235,135,535,335,85,485,285,185,585,385,10,410,210,610,110,510,310,60,460,260,160,560,360,
241,141,541,341,91,491,291,191,591,391,16,416,216,616,116,516,316,66,466,266,166,566,366,41,441,
529,329,79,479,279,179,579,379,4,404,204,604,104,504,304,54,454,254,154,554,354,29,429,229,129,
94,494,294,194,594,394,19,419,219,619,119,519,319,69,469,269,169,569,369,44,444,244,144,544,344,
282,182,582,382,7,407,207,607,107,507,307,57,457,257,157,557,357,32,432,232,132,532,332,82,482,
588,388,13,413,213,613,113,513,313,63,463,263,163,563,363,38,438,238,138,538,338,88,488,288,188,
0,400,200,600,100,500,300,50,450,250,150,550,350,25,425,225,125,525,325,75,475,275,175,575,3
};
int tableh11[] = { /* 27 x 27 data */
2,658,118,550,334,64,496,280,712,172,604,388,37,469,253,685,145,577,361,91,523,307,199,631,415,10,1,
125,557,341,71,503,287,719,179,611,395,44,476,260,692,152,584,368,98,530,314,206,638,422,17,449,233,665,
327,57,489,273,705,165,597,381,30,462,246,678,138,570,354,84,516,300,192,624,408,405,435,219,651,111,543,
511,295,727,187,619,403,52,484,268,700,160,592,376,106,538,322,214,646,430,25,457,241,673,133,565,349,79,
714,174,606,390,39,471,255,687,147,579,363,93,525,309,201,633,417,12,444,228,660,120,552,336,66,498,282,
613,397,46,478,262,694,154,586,370,100,532,316,208,640,424,19,451,235,667,127,559,343,73,505,289,721,181,
32,464,248,680,140,572,356,86,518,302,194,626,410,5,437,221,653,113,545,329,59,491,275,707,167,599,383,
265,697,157,589,373,103,535,319,211,643,427,22,454,238,670,130,562,346,76,508,292,724,184,616,400,49,481,
143,575,359,89,521,305,197,629,413,8,440,224,656,116,548,332,62,494,278,710,170,602,386,35,467,251,683,
366,96,528,312,204,636,420,15,447,231,663,123,555,339,69,501,285,717,177,609,393,42,474,258,690,150,582,
514,298,190,622,406,442,433,217,649,109,541,325,55,487,271,703,163,595,379,28,460,244,676,136,568,352,82,
215,647,431,26,458,242,674,134,566,350,80,512,296,728,188,620,404,53,485,269,701,161,593,377,107,539,323,
418,13,445,229,661,121,553,337,67,499,283,715,175,607,391,40,472,256,688,148,580,364,94,526,310,202,634,
452,236,668,128,560,344,74,506,290,722,182,614,398,47,479,263,695,155,587,371,101,533,317,209,641,425,20,
654,114,546,330,60,492,276,708,168,600,384,33,465,249,681,141,573,357,87,519,303,195,627,411,6,438,222,
563,347,77,509,293,725,185,617,401,50,482,266,698,158,590,374,104,536,320,212,644,428,23,455,239,671,131,
63,495,279,711,171,603,387,36,468,252,684,144,576,360,90,522,306,198,630,414,9,441,225,657,117,549,333,
286,718,178,610,394,43,475,259,691,151,583,367,97,529,313,205,637,421,16,448,232,664,124,556,340,70,502,
164,596,380,29,461,245,677,137,569,353,83,515,299,191,623,407,226,434,218,650,110,542,326,56,488,272,704,
402,51,483,267,699,159,591,375,105,537,321,213,645,429,24,456,240,672,132,564,348,78,510,294,726,186,618,
470,254,686,146,578,362,92,524,308,200,632,416,11,443,227,659,119,551,335,65,497,281,713,173,605,389,38,
693,153,585,369,99,531,315,207,639,423,18,450,234,666,126,558,342,72,504,288,720,180,612,396,45,477,261,
571,355,85,517,301,193,625,409,4,436,220,652,112,544,328,58,490,274,706,166,598,382,31,463,247,679,139,
102,534,318,210,642,426,21,453,237,669,129,561,345,75,507,291,723,183,615,399,48,480,264,696,156,588,372,
304,196,628,412,7,439,223,655,115,547,331,61,493,277,709,169,601,385,34,466,250,682,142,574,358,88,520,
635,419,14,446,230,662,122,554,338,68,500,284,716,176,608,392,41,473,257,689,149,581,365,95,527,311,203,
0,432,216,648,108,540,324,54,486,270,702,162,594,378,27,459,243,675,135,567,351,81,513,297,189,621,3
};
int tableh12[] = { /* 29 x 29 data */
2,703,123,587,355,819,65,529,297,761,181,645,413,36,500,268,732,152,616,384,94,558,326,790,210,674,442,7,1,
141,605,373,837,83,547,315,779,199,663,431,54,518,286,750,170,634,402,112,576,344,808,228,692,460,25,489,257,721,
359,823,69,533,301,765,185,649,417,40,504,272,736,156,620,388,98,562,330,794,214,678,446,11,475,243,707,127,591,
76,540,308,772,192,656,424,47,511,279,743,163,627,395,105,569,337,801,221,685,453,18,482,250,714,134,598,366,830,
293,757,177,641,409,32,496,264,728,148,612,380,90,554,322,786,206,670,438,435,467,235,699,119,583,351,815,61,525,
201,665,433,56,520,288,752,172,636,404,114,578,346,810,230,694,462,27,491,259,723,143,607,375,839,85,549,317,781,
419,42,506,274,738,158,622,390,100,564,332,796,216,680,448,13,477,245,709,129,593,361,825,71,535,303,767,187,651,
513,281,745,165,629,397,107,571,339,803,223,687,455,20,484,252,716,136,600,368,832,78,542,310,774,194,658,426,49,
730,150,614,382,92,556,324,788,208,672,440,5,469,237,701,121,585,353,817,63,527,295,759,179,643,411,34,498,266,
632,400,110,574,342,806,226,690,458,23,487,255,719,139,603,371,835,81,545,313,777,197,661,429,52,516,284,748,168,
96,560,328,792,212,676,444,9,473,241,705,125,589,357,821,67,531,299,763,183,647,415,38,502,270,734,154,618,386,
335,799,219,683,451,16,480,248,712,132,596,364,828,74,538,306,770,190,654,422,45,509,277,741,161,625,393,103,567,
204,668,436,471,465,233,697,117,581,349,813,59,523,291,755,175,639,407,30,494,262,726,146,610,378,88,552,320,784,
463,28,492,260,724,144,608,376,840,86,550,318,782,202,666,434,57,521,289,753,173,637,405,115,579,347,811,231,695,
478,246,710,130,594,362,826,72,536,304,768,188,652,420,43,507,275,739,159,623,391,101,565,333,797,217,681,449,14,
717,137,601,369,833,79,543,311,775,195,659,427,50,514,282,746,166,630,398,108,572,340,804,224,688,456,21,485,253,
586,354,818,64,528,296,760,180,644,412,35,499,267,731,151,615,383,93,557,325,789,209,673,441,6,470,238,702,122,
836,82,546,314,778,198,662,430,53,517,285,749,169,633,401,111,575,343,807,227,691,459,24,488,256,720,140,604,372,
532,300,764,184,648,416,39,503,271,735,155,619,387,97,561,329,793,213,677,445,10,474,242,706,126,590,358,822,68,
771,191,655,423,46,510,278,742,162,626,394,104,568,336,800,220,684,452,17,481,249,713,133,597,365,829,75,539,307,
640,408,31,495,263,727,147,611,379,89,553,321,785,205,669,437,239,466,234,698,118,582,350,814,60,524,292,756,176,
55,519,287,751,171,635,403,113,577,345,809,229,693,461,26,490,258,722,142,606,374,838,84,548,316,780,200,664,432,
273,737,157,621,389,99,563,331,795,215,679,447,12,476,244,708,128,592,360,824,70,534,302,766,186,650,418,41,505,
164,628,396,106,570,338,802,222,686,454,19,483,251,715,135,599,367,831,77,541,309,773,193,657,425,48,512,280,744,
381,91,555,323,787,207,671,439,4,468,236,700,120,584,352,816,62,526,294,758,178,642,410,33,497,265,729,149,613,
573,341,805,225,689,457,22,486,254,718,138,602,370,834,80,544,312,776,196,660,428,51,515,283,747,167,631,399,109,
791,211,675,443,8,472,240,704,124,588,356,820,66,530,298,762,182,646,414,37,501,269,733,153,617,385,95,559,327,
682,450,15,479,247,711,131,595,363,827,73,537,305,769,189,653,421,44,508,276,740,160,624,392,102,566,334,798,218,
0,464,232,696,116,580,348,812,58,522,290,754,174,638,406,29,493,261,725,145,609,377,87,551,319,783,203,667,3
};
int tableh13[] = { /* 31 x 31 data */
2,759,139,635,387,883,77,573,325,821,201,697,449,945,46,542,294,790,170,666,418,914,108,604,356,852,232,728,480,15,1,
147,643,395,891,85,581,333,829,209,705,457,953,54,550,302,798,178,674,426,922,116,612,364,860,240,736,488,23,519,271,767,
379,875,69,565,317,813,193,689,441,937,38,534,286,782,162,658,410,906,100,596,348,844,224,720,472,7,503,255,751,131,627,
89,585,337,833,213,709,461,957,58,554,306,802,182,678,430,926,120,616,368,864,244,740,492,27,523,275,771,151,647,399,895,
321,817,197,693,445,941,42,538,290,786,166,662,414,910,104,600,352,848,228,724,476,11,507,259,755,135,631,383,879,73,569,
205,701,453,949,50,546,298,794,174,670,422,918,112,608,360,856,236,732,484,19,515,267,763,143,639,391,887,81,577,329,825,
437,933,34,530,282,778,158,654,406,902,96,592,344,840,220,716,468,465,499,251,747,127,623,375,871,65,561,313,809,189,685,
60,556,308,804,184,680,432,928,122,618,370,866,246,742,494,29,525,277,773,153,649,401,897,91,587,339,835,215,711,463,959,
292,788,168,664,416,912,106,602,354,850,230,726,478,13,509,261,757,137,633,385,881,75,571,323,819,199,695,447,943,44,540,
176,672,424,920,114,610,362,858,238,734,486,21,517,269,765,145,641,393,889,83,579,331,827,207,703,455,951,52,548,300,796,
408,904,98,594,346,842,222,718,470,5,501,253,749,129,625,377,873,67,563,315,811,191,687,439,935,36,532,284,780,160,656,
118,614,366,862,242,738,490,25,521,273,769,149,645,397,893,87,583,335,831,211,707,459,955,56,552,304,800,180,676,428,924,
350,846,226,722,474,9,505,257,753,133,629,381,877,71,567,319,815,195,691,443,939,40,536,288,784,164,660,412,908,102,598,
234,730,482,17,513,265,761,141,637,389,885,79,575,327,823,203,699,451,947,48,544,296,792,172,668,420,916,110,606,358,854,
466,511,497,249,745,125,621,373,869,63,559,311,807,187,683,435,931,32,528,280,776,156,652,404,900,94,590,342,838,218,714,
526,278,774,154,650,402,898,92,588,340,836,216,712,464,960,61,557,309,805,185,681,433,929,123,619,371,867,247,743,495,30,
758,138,634,386,882,76,572,324,820,200,696,448,944,45,541,293,789,169,665,417,913,107,603,355,851,231,727,479,14,510,262,
642,394,890,84,580,332,828,208,704,456,952,53,549,301,797,177,673,425,921,115,611,363,859,239,735,487,22,518,270,766,146,
874,68,564,316,812,192,688,440,936,37,533,285,781,161,657,409,905,99,595,347,843,223,719,471,6,502,254,750,130,626,378,
584,336,832,212,708,460,956,57,553,305,801,181,677,429,925,119,615,367,863,243,739,491,26,522,274,770,150,646,398,894,88,
816,196,692,444,940,41,537,289,785,165,661,413,909,103,599,351,847,227,723,475,10,506,258,754,134,630,382,878,72,568,320,
700,452,948,49,545,297,793,173,669,421,917,111,607,359,855,235,731,483,18,514,266,762,142,638,390,886,80,576,328,824,204,
932,33,529,281,777,157,653,405,901,95,591,343,839,219,715,467,263,498,250,746,126,622,374,870,64,560,312,808,188,684,436,
555,307,803,183,679,431,927,121,617,369,865,245,741,493,28,524,276,772,152,648,400,896,90,586,338,834,214,710,462,958,59,
787,167,663,415,911,105,601,353,849,229,725,477,12,508,260,756,136,632,384,880,74,570,322,818,198,694,446,942,43,539,291,
671,423,919,113,609,361,857,237,733,485,20,516,268,764,144,640,392,888,82,578,330,826,206,702,454,950,51,547,299,795,175,
903,97,593,345,841,221,717,469,4,500,252,748,128,624,376,872,66,562,314,810,190,686,438,934,35,531,283,779,159,655,407,
613,365,861,241,737,489,24,520,272,768,148,644,396,892,86,582,334,830,210,706,458,954,55,551,303,799,179,675,427,923,117,
845,225,721,473,8,504,256,752,132,628,380,876,70,566,318,814,194,690,442,938,39,535,287,783,163,659,411,907,101,597,349,
729,481,16,512,264,760,140,636,388,884,78,574,326,822,202,698,450,946,47,543,295,791,171,667,419,915,109,605,357,853,233,
0,496,248,744,124,620,372,868,62,558,310,806,186,682,434,930,31,527,279,775,155,651,403,899,93,589,341,837,217,713,3
};
int tableh14[] = { /* 33 x 33 data */
2,265,793,133,661,397,925,67,595,331,859,199,727,463,991,34,562,298,826,166,694,430,958,100,628,364,892,232,760,496,1024,1057,1,
824,164,692,428,956,98,626,362,890,230,758,494,1022,65,593,329,857,197,725,461,989,131,659,395,923,263,791,527,1055,32,1088,560,296,
676,412,940,82,610,346,874,214,742,478,1006,49,577,313,841,181,709,445,973,115,643,379,907,247,775,511,1039,16,1072,544,280,808,148,
948,90,618,354,882,222,750,486,1014,57,585,321,849,189,717,453,981,123,651,387,915,255,783,519,1047,24,1080,552,288,816,156,684,420,
602,338,866,206,734,470,998,41,569,305,833,173,701,437,965,107,635,371,899,239,767,503,1031,8,1064,536,272,800,140,668,404,932,74,
886,226,754,490,1018,61,589,325,853,193,721,457,985,127,655,391,919,259,787,523,1051,28,1084,556,292,820,160,688,424,952,94,622,358,
738,474,1002,45,573,309,837,177,705,441,969,111,639,375,903,243,771,507,1035,12,1068,540,276,804,144,672,408,936,78,606,342,870,210,
1010,53,581,317,845,185,713,449,977,119,647,383,911,251,779,515,1043,20,1076,548,284,812,152,680,416,944,86,614,350,878,218,746,482,
565,301,829,169,697,433,961,103,631,367,895,235,763,499,1027,4,1060,532,268,796,136,664,400,928,70,598,334,862,202,730,466,994,37,
855,195,723,459,987,129,657,393,921,261,789,525,1053,30,1086,558,294,822,162,690,426,954,96,624,360,888,228,756,492,1020,63,591,327,
707,443,971,113,641,377,905,245,773,509,1037,14,1070,542,278,806,146,674,410,938,80,608,344,872,212,740,476,1004,47,575,311,839,179,
979,121,649,385,913,253,781,517,1045,22,1078,550,286,814,154,682,418,946,88,616,352,880,220,748,484,1012,55,583,319,847,187,715,451,
633,369,897,237,765,501,1029,6,1062,534,270,798,138,666,402,930,72,600,336,864,204,732,468,996,39,567,303,831,171,699,435,963,105,
917,257,785,521,1049,26,1082,554,290,818,158,686,422,950,92,620,356,884,224,752,488,1016,59,587,323,851,191,719,455,983,125,653,389,
769,505,1033,10,1066,538,274,802,142,670,406,934,76,604,340,868,208,736,472,1000,43,571,307,835,175,703,439,967,109,637,373,901,241,
1041,18,1074,546,282,810,150,678,414,942,84,612,348,876,216,744,480,1008,51,579,315,843,183,711,447,975,117,645,381,909,249,777,513,
1058,530,266,794,134,662,398,926,68,596,332,860,200,728,464,992,35,563,299,827,167,695,431,959,101,629,365,893,233,761,497,1025,529,
295,823,163,691,427,955,97,625,361,889,229,757,493,1021,64,592,328,856,196,724,460,988,130,658,394,922,262,790,526,1054,31,1087,559,
147,675,411,939,81,609,345,873,213,741,477,1005,48,576,312,840,180,708,444,972,114,642,378,906,246,774,510,1038,15,1071,543,279,807,
419,947,89,617,353,881,221,749,485,1013,56,584,320,848,188,716,452,980,122,650,386,914,254,782,518,1046,23,1079,551,287,815,155,683,
73,601,337,865,205,733,469,997,40,568,304,832,172,700,436,964,106,634,370,898,238,766,502,1030,7,1063,535,271,799,139,667,403,931,
357,885,225,753,489,1017,60,588,324,852,192,720,456,984,126,654,390,918,258,786,522,1050,27,1083,555,291,819,159,687,423,951,93,621,
209,737,473,1001,44,572,308,836,176,704,440,968,110,638,374,902,242,770,506,1034,11,1067,539,275,803,143,671,407,935,77,605,341,869,
481,1009,52,580,316,844,184,712,448,976,118,646,382,910,250,778,514,1042,19,1075,547,283,811,151,679,415,943,85,613,349,877,217,745,
36,564,300,828,168,696,432,960,102,630,366,894,234,762,498,1026,1023,1059,531,267,795,135,663,399,927,69,597,333,861,201,729,465,993,
326,854,194,722,458,986,128,656,392,920,260,788,524,1052,29,1085,557,293,821,161,689,425,953,95,623,359,887,227,755,491,1019,62,590,
178,706,442,970,112,640,376,904,244,772,508,1036,13,1069,541,277,805,145,673,409,937,79,607,343,871,211,739,475,1003,46,574,310,838,
450,978,120,648,384,912,252,780,516,1044,21,1077,549,285,813,153,681,417,945,87,615,351,879,219,747,483,1011,54,582,318,846,186,714,
104,632,368,896,236,764,500,1028,5,1061,533,269,797,137,665,401,929,71,599,335,863,203,731,467,995,38,566,302,830,170,698,434,962,
388,916,256,784,520,1048,25,1081,553,289,817,157,685,421,949,91,619,355,883,223,751,487,1015,58,586,322,850,190,718,454,982,124,652,
240,768,504,1032,9,1065,537,273,801,141,669,405,933,75,603,339,867,207,735,471,999,42,570,306,834,174,702,438,966,108,636,372,900,
512,1040,17,1073,545,281,809,149,677,413,941,83,611,347,875,215,743,479,1007,50,578,314,842,182,710,446,974,116,644,380,908,248,776,
0,1056,528,264,792,132,660,396,924,66,594,330,858,198,726,462,990,33,561,297,825,165,693,429,957,99,627,363,891,231,759,495,3
};
int tableh15[] = { /* 35 x 35 data */
2,290,850,150,710,430,990,80,1200,640,360,920,220,780,500,1060,45,1165,605,325,885,185,745,465,1025,115,675,395,955,255,815,535,1095,10,1,
859,159,719,439,999,89,1209,649,369,929,229,789,509,1069,54,1174,614,334,894,194,754,474,1034,124,684,404,964,264,824,544,1104,19,1139,579,299,
701,421,981,71,1191,631,351,911,211,771,491,1051,36,1156,596,316,876,176,736,456,1016,106,666,386,946,246,806,526,1086,1130,1121,561,281,841,141,
1014,104,1224,664,384,944,244,804,524,1084,69,1189,629,349,909,209,769,489,1049,139,699,419,979,279,839,559,1119,34,1154,594,314,874,174,734,454,
1207,647,367,927,227,787,507,1067,52,1172,612,332,892,192,752,472,1032,122,682,402,962,262,822,542,1102,17,1137,577,297,857,157,717,437,997,87,
376,936,236,796,516,1076,61,1181,621,341,901,201,761,481,1041,131,691,411,971,271,831,551,1111,26,1146,586,306,866,166,726,446,1006,96,1216,656,
218,778,498,1058,43,1163,603,323,883,183,743,463,1023,113,673,393,953,253,813,533,1093,8,1128,568,288,848,148,708,428,988,78,1198,638,358,918,
520,1080,65,1185,625,345,905,205,765,485,1045,135,695,415,975,275,835,555,1115,30,1150,590,310,870,170,730,450,1010,100,1220,660,380,940,240,800,
48,1168,608,328,888,188,748,468,1028,118,678,398,958,258,818,538,1098,13,1133,573,293,853,153,713,433,993,83,1203,643,363,923,223,783,503,1063,
617,337,897,197,757,477,1037,127,687,407,967,267,827,547,1107,22,1142,582,302,862,162,722,442,1002,92,1212,652,372,932,232,792,512,1072,57,1177,
879,179,739,459,1019,109,669,389,949,249,809,529,1089,4,1124,564,284,844,144,704,424,984,74,1194,634,354,914,214,774,494,1054,39,1159,599,319,
767,487,1047,137,697,417,977,277,837,557,1117,32,1152,592,312,872,172,732,452,1012,102,1222,662,382,942,242,802,522,1082,67,1187,627,347,907,207,
1030,120,680,400,960,260,820,540,1100,15,1135,575,295,855,155,715,435,995,85,1205,645,365,925,225,785,505,1065,50,1170,610,330,890,190,750,470,
689,409,969,269,829,549,1109,24,1144,584,304,864,164,724,444,1004,94,1214,654,374,934,234,794,514,1074,59,1179,619,339,899,199,759,479,1039,129,
951,251,811,531,1091,6,1126,566,286,846,146,706,426,986,76,1196,636,356,916,216,776,496,1056,41,1161,601,321,881,181,741,461,1021,111,671,391,
833,553,1113,28,1148,588,308,868,168,728,448,1008,98,1218,658,378,938,238,798,518,1078,63,1183,623,343,903,203,763,483,1043,133,693,413,973,273,
1096,11,1131,571,291,851,151,711,431,991,81,1201,641,361,921,221,781,501,1061,46,1166,606,326,886,186,746,466,1026,116,676,396,956,256,816,536,
1140,580,300,860,160,720,440,1000,90,1210,650,370,930,230,790,510,1070,55,1175,615,335,895,195,755,475,1035,125,685,405,965,265,825,545,1105,20,
282,842,142,702,422,982,72,1192,632,352,912,212,772,492,1052,37,1157,597,317,877,177,737,457,1017,107,667,387,947,247,807,527,1087,570,1122,562,
173,733,453,1013,103,1223,663,383,943,243,803,523,1083,68,1188,628,348,908,208,768,488,1048,138,698,418,978,278,838,558,1118,33,1153,593,313,873,
436,996,86,1206,646,366,926,226,786,506,1066,51,1171,611,331,891,191,751,471,1031,121,681,401,961,261,821,541,1101,16,1136,576,296,856,156,716,
95,1215,655,375,935,235,795,515,1075,60,1180,620,340,900,200,760,480,1040,130,690,410,970,270,830,550,1110,25,1145,585,305,865,165,725,445,1005,
637,357,917,217,777,497,1057,42,1162,602,322,882,182,742,462,1022,112,672,392,952,252,812,532,1092,7,1127,567,287,847,147,707,427,987,77,1197,
939,239,799,519,1079,64,1184,624,344,904,204,764,484,1044,134,694,414,974,274,834,554,1114,29,1149,589,309,869,169,729,449,1009,99,1219,659,379,
782,502,1062,47,1167,607,327,887,187,747,467,1027,117,677,397,957,257,817,537,1097,12,1132,572,292,852,152,712,432,992,82,1202,642,362,922,222,
1071,56,1176,616,336,896,196,756,476,1036,126,686,406,966,266,826,546,1106,21,1141,581,301,861,161,721,441,1001,91,1211,651,371,931,231,791,511,
1158,598,318,878,178,738,458,1018,108,668,388,948,248,808,528,1088,1085,1123,563,283,843,143,703,423,983,73,1193,633,353,913,213,773,493,1053,38,
346,906,206,766,486,1046,136,696,416,976,276,836,556,1116,31,1151,591,311,871,171,731,451,1011,101,1221,661,381,941,241,801,521,1081,66,1186,626,
189,749,469,1029,119,679,399,959,259,819,539,1099,14,1134,574,294,854,154,714,434,994,84,1204,644,364,924,224,784,504,1064,49,1169,609,329,889,
478,1038,128,688,408,968,268,828,548,1108,23,1143,583,303,863,163,723,443,1003,93,1213,653,373,933,233,793,513,1073,58,1178,618,338,898,198,758,
110,670,390,950,250,810,530,1090,5,1125,565,285,845,145,705,425,985,75,1195,635,355,915,215,775,495,1055,40,1160,600,320,880,180,740,460,1020,
412,972,272,832,552,1112,27,1147,587,307,867,167,727,447,1007,97,1217,657,377,937,237,797,517,1077,62,1182,622,342,902,202,762,482,1042,132,692,
254,814,534,1094,9,1129,569,289,849,149,709,429,989,79,1199,639,359,919,219,779,499,1059,44,1164,604,324,884,184,744,464,1024,114,674,394,954,
543,1103,18,1138,578,298,858,158,718,438,998,88,1208,648,368,928,228,788,508,1068,53,1173,613,333,893,193,753,473,1033,123,683,403,963,263,823,
0,1120,560,280,840,140,700,420,980,70,1190,630,350,910,210,770,490,1050,35,1155,595,315,875,175,735,455,1015,105,665,385,945,245,805,525,3
};
int tableh16[] = { /* 37 x 37 data */
2,302,894,154,1338,746,450,1042,80,1264,672,376,968,228,820,524,1116,43,1227,635,339,931,191,783,487,1079,117,1301,709,413,1005,265,857,561,1153,6,1,
917,177,1361,769,473,1065,103,1287,695,399,991,251,843,547,1139,66,1250,658,362,954,214,806,510,1102,140,1324,732,436,1028,288,880,584,1176,29,1213,621,325,
1343,751,455,1047,85,1269,677,381,973,233,825,529,1121,48,1232,640,344,936,196,788,492,1084,122,1306,714,418,1010,270,862,566,1158,11,1195,603,307,899,159,
464,1056,94,1278,686,390,982,242,834,538,1130,57,1241,649,353,945,205,797,501,1093,131,1315,723,427,1019,279,871,575,1167,20,1204,612,316,908,168,1352,760,
75,1259,667,371,963,223,815,519,1111,38,1222,630,334,926,186,778,482,1074,112,1296,704,408,1000,260,852,556,1148,1190,1185,593,297,889,149,1333,741,445,1037,
702,406,998,258,850,554,1146,73,1257,665,369,961,221,813,517,1109,147,1331,739,443,1035,295,887,591,1183,36,1220,628,332,924,184,1368,776,480,1072,110,1294,
980,240,832,536,1128,55,1239,647,351,943,203,795,499,1091,129,1313,721,425,1017,277,869,573,1165,18,1202,610,314,906,166,1350,758,462,1054,92,1276,684,388,
841,545,1137,64,1248,656,360,952,212,804,508,1100,138,1322,730,434,1026,286,878,582,1174,27,1211,619,323,915,175,1359,767,471,1063,101,1285,693,397,989,249,
1119,46,1230,638,342,934,194,786,490,1082,120,1304,712,416,1008,268,860,564,1156,9,1193,601,305,897,157,1341,749,453,1045,83,1267,675,379,971,231,823,527,
1253,661,365,957,217,809,513,1105,143,1327,735,439,1031,291,883,587,1179,32,1216,624,328,920,180,1364,772,476,1068,106,1290,698,402,994,254,846,550,1142,69,
347,939,199,791,495,1087,125,1309,717,421,1013,273,865,569,1161,14,1198,606,310,902,162,1346,754,458,1050,88,1272,680,384,976,236,828,532,1124,51,1235,643,
208,800,504,1096,134,1318,726,430,1022,282,874,578,1170,23,1207,615,319,911,171,1355,763,467,1059,97,1281,689,393,985,245,837,541,1133,60,1244,652,356,948,
485,1077,115,1299,707,411,1003,263,855,559,1151,4,1188,596,300,892,152,1336,744,448,1040,78,1262,670,374,966,226,818,522,1114,41,1225,633,337,929,189,781,
145,1329,737,441,1033,293,885,589,1181,34,1218,626,330,922,182,1366,774,478,1070,108,1292,700,404,996,256,848,552,1144,71,1255,663,367,959,219,811,515,1107,
719,423,1015,275,867,571,1163,16,1200,608,312,904,164,1348,756,460,1052,90,1274,682,386,978,238,830,534,1126,53,1237,645,349,941,201,793,497,1089,127,1311,
1024,284,876,580,1172,25,1209,617,321,913,173,1357,765,469,1061,99,1283,691,395,987,247,839,543,1135,62,1246,654,358,950,210,802,506,1098,136,1320,728,432,
858,562,1154,7,1191,599,303,895,155,1339,747,451,1043,81,1265,673,377,969,229,821,525,1117,44,1228,636,340,932,192,784,488,1080,118,1302,710,414,1006,266,
1177,30,1214,622,326,918,178,1362,770,474,1066,104,1288,696,400,992,252,844,548,1140,67,1251,659,363,955,215,807,511,1103,141,1325,733,437,1029,289,881,585,
1196,604,308,900,160,1344,752,456,1048,86,1270,678,382,974,234,826,530,1122,49,1233,641,345,937,197,789,493,1085,123,1307,715,419,1011,271,863,567,1159,12,
317,909,169,1353,761,465,1057,95,1279,687,391,983,243,835,539,1131,58,1242,650,354,946,206,798,502,1094,132,1316,724,428,1020,280,872,576,1168,21,1205,613,
150,1334,742,446,1038,76,1260,668,372,964,224,816,520,1112,39,1223,631,335,927,187,779,483,1075,113,1297,705,409,1001,261,853,557,1149,598,1186,594,298,890,
775,479,1071,109,1293,701,405,997,257,849,553,1145,72,1256,664,368,960,220,812,516,1108,146,1330,738,442,1034,294,886,590,1182,35,1219,627,331,923,183,1367,
1053,91,1275,683,387,979,239,831,535,1127,54,1238,646,350,942,202,794,498,1090,128,1312,720,424,1016,276,868,572,1164,17,1201,609,313,905,165,1349,757,461,
1284,692,396,988,248,840,544,1136,63,1247,655,359,951,211,803,507,1099,137,1321,729,433,1025,285,877,581,1173,26,1210,618,322,914,174,1358,766,470,1062,100,
378,970,230,822,526,1118,45,1229,637,341,933,193,785,489,1081,119,1303,711,415,1007,267,859,563,1155,8,1192,600,304,896,156,1340,748,452,1044,82,1266,674,
253,845,549,1141,68,1252,660,364,956,216,808,512,1104,142,1326,734,438,1030,290,882,586,1178,31,1215,623,327,919,179,1363,771,475,1067,105,1289,697,401,993,
531,1123,50,1234,642,346,938,198,790,494,1086,124,1308,716,420,1012,272,864,568,1160,13,1197,605,309,901,161,1345,753,457,1049,87,1271,679,383,975,235,827,
59,1243,651,355,947,207,799,503,1095,133,1317,725,429,1021,281,873,577,1169,22,1206,614,318,910,170,1354,762,466,1058,96,1280,688,392,984,244,836,540,1132,
632,336,928,188,780,484,1076,114,1298,706,410,1002,262,854,558,1150,1147,1187,595,299,891,151,1335,743,447,1039,77,1261,669,373,965,225,817,521,1113,40,1224,
958,218,810,514,1106,144,1328,736,440,1032,292,884,588,1180,33,1217,625,329,921,181,1365,773,477,1069,107,1291,699,403,995,255,847,551,1143,70,1254,662,366,
792,496,1088,126,1310,718,422,1014,274,866,570,1162,15,1199,607,311,903,163,1347,755,459,1051,89,1273,681,385,977,237,829,533,1125,52,1236,644,348,940,200,
1097,135,1319,727,431,1023,283,875,579,1171,24,1208,616,320,912,172,1356,764,468,1060,98,1282,690,394,986,246,838,542,1134,61,1245,653,357,949,209,801,505,
1300,708,412,1004,264,856,560,1152,5,1189,597,301,893,153,1337,745,449,1041,79,1263,671,375,967,227,819,523,1115,42,1226,634,338,930,190,782,486,1078,116,
435,1027,287,879,583,1175,28,1212,620,324,916,176,1360,768,472,1064,102,1286,694,398,990,250,842,546,1138,65,1249,657,361,953,213,805,509,1101,139,1323,731,
269,861,565,1157,10,1194,602,306,898,158,1342,750,454,1046,84,1268,676,380,972,232,824,528,1120,47,1231,639,343,935,195,787,491,1083,121,1305,713,417,1009,
574,1166,19,1203,611,315,907,167,1351,759,463,1055,93,1277,685,389,981,241,833,537,1129,56,1240,648,352,944,204,796,500,1092,130,1314,722,426,1018,278,870,
0,1184,592,296,888,148,1332,740,444,1036,74,1258,666,370,962,222,814,518,1110,37,1221,629,333,925,185,777,481,1073,111,1295,703,407,999,259,851,555,3
};
int tableh17[] = { /* 39 x 39 data */
2,328,952,172,1420,796,484,1108,94,1342,718,406,1030,250,1498,874,562,1186,55,1303,679,367,991,211,1459,835,523,1147,133,1381,757,445,1069,289,913,601,1225,16,1,
962,182,1430,806,494,1118,104,1352,728,416,1040,260,1508,884,572,1196,65,1313,689,377,1001,221,1469,845,533,1157,143,1391,767,455,1079,299,923,611,1235,26,1274,650,338,
1410,786,474,1098,84,1332,708,396,1020,240,1488,864,552,1176,45,1293,669,357,981,201,1449,825,513,1137,123,1371,747,435,1059,279,903,591,1215,6,1254,630,318,942,162,
499,1123,109,1357,733,421,1045,265,1513,889,577,1201,70,1318,694,382,1006,226,1474,850,538,1162,148,1396,772,460,1084,304,928,616,1240,31,1279,655,343,967,187,1435,811,
89,1337,713,401,1025,245,1493,869,557,1181,50,1298,674,362,986,206,1454,830,518,1142,128,1376,752,440,1064,284,908,596,1220,11,1259,635,323,947,167,1415,791,479,1103,
723,411,1035,255,1503,879,567,1191,60,1308,684,372,996,216,1464,840,528,1152,138,1386,762,450,1074,294,918,606,1230,21,1269,645,333,957,177,1425,801,489,1113,99,1347,
1015,235,1483,859,547,1171,40,1288,664,352,976,196,1444,820,508,1132,118,1366,742,430,1054,274,898,586,1210,1264,1249,625,313,937,157,1405,781,469,1093,79,1327,703,391,
1520,896,584,1208,77,1325,701,389,1013,233,1481,857,545,1169,155,1403,779,467,1091,311,935,623,1247,38,1286,662,350,974,194,1442,818,506,1130,116,1364,740,428,1052,272,
565,1189,58,1306,682,370,994,214,1462,838,526,1150,136,1384,760,448,1072,292,916,604,1228,19,1267,643,331,955,175,1423,799,487,1111,97,1345,721,409,1033,253,1501,877,
68,1316,692,380,1004,224,1472,848,536,1160,146,1394,770,458,1082,302,926,614,1238,29,1277,653,341,965,185,1433,809,497,1121,107,1355,731,419,1043,263,1511,887,575,1199,
672,360,984,204,1452,828,516,1140,126,1374,750,438,1062,282,906,594,1218,9,1257,633,321,945,165,1413,789,477,1101,87,1335,711,399,1023,243,1491,867,555,1179,48,1296,
1009,229,1477,853,541,1165,151,1399,775,463,1087,307,931,619,1243,34,1282,658,346,970,190,1438,814,502,1126,112,1360,736,424,1048,268,1516,892,580,1204,73,1321,697,385,
1457,833,521,1145,131,1379,755,443,1067,287,911,599,1223,14,1262,638,326,950,170,1418,794,482,1106,92,1340,716,404,1028,248,1496,872,560,1184,53,1301,677,365,989,209,
531,1155,141,1389,765,453,1077,297,921,609,1233,24,1272,648,336,960,180,1428,804,492,1116,102,1350,726,414,1038,258,1506,882,570,1194,63,1311,687,375,999,219,1467,843,
121,1369,745,433,1057,277,901,589,1213,4,1252,628,316,940,160,1408,784,472,1096,82,1330,706,394,1018,238,1486,862,550,1174,43,1291,667,355,979,199,1447,823,511,1135,
777,465,1089,309,933,621,1245,36,1284,660,348,972,192,1440,816,504,1128,114,1362,738,426,1050,270,1518,894,582,1206,75,1323,699,387,1011,231,1479,855,543,1167,153,1401,
1070,290,914,602,1226,17,1265,641,329,953,173,1421,797,485,1109,95,1343,719,407,1031,251,1499,875,563,1187,56,1304,680,368,992,212,1460,836,524,1148,134,1382,758,446,
924,612,1236,27,1275,651,339,963,183,1431,807,495,1119,105,1353,729,417,1041,261,1509,885,573,1197,66,1314,690,378,1002,222,1470,846,534,1158,144,1392,768,456,1080,300,
1216,7,1255,631,319,943,163,1411,787,475,1099,85,1333,709,397,1021,241,1489,865,553,1177,46,1294,670,358,982,202,1450,826,514,1138,124,1372,748,436,1060,280,904,592,
1280,656,344,968,188,1436,812,500,1124,110,1358,734,422,1046,266,1514,890,578,1202,71,1319,695,383,1007,227,1475,851,539,1163,149,1397,773,461,1085,305,929,617,1241,32,
324,948,168,1416,792,480,1104,90,1338,714,402,1026,246,1494,870,558,1182,51,1299,675,363,987,207,1455,831,519,1143,129,1377,753,441,1065,285,909,597,1221,12,1260,636,
178,1426,802,490,1114,100,1348,724,412,1036,256,1504,880,568,1192,61,1309,685,373,997,217,1465,841,529,1153,139,1387,763,451,1075,295,919,607,1231,22,1270,646,334,958,
782,470,1094,80,1328,704,392,1016,236,1484,860,548,1172,41,1289,665,353,977,197,1445,821,509,1133,119,1367,743,431,1055,275,899,587,1211,640,1250,626,314,938,158,1406,
1129,115,1363,739,427,1051,271,1519,895,583,1207,76,1324,700,388,1012,232,1480,856,544,1168,154,1402,778,466,1090,310,934,622,1246,37,1285,661,349,973,193,1441,817,505,
1344,720,408,1032,252,1500,876,564,1188,57,1305,681,369,993,213,1461,837,525,1149,135,1383,759,447,1071,291,915,603,1227,18,1266,642,330,954,174,1422,798,486,1110,96,
418,1042,262,1510,886,574,1198,67,1315,691,379,1003,223,1471,847,535,1159,145,1393,769,457,1081,301,925,613,1237,28,1276,652,340,964,184,1432,808,496,1120,106,1354,730,
242,1490,866,554,1178,47,1295,671,359,983,203,1451,827,515,1139,125,1373,749,437,1061,281,905,593,1217,8,1256,632,320,944,164,1412,788,476,1100,86,1334,710,398,1022,
891,579,1203,72,1320,696,384,1008,228,1476,852,540,1164,150,1398,774,462,1086,306,930,618,1242,33,1281,657,345,969,189,1437,813,501,1125,111,1359,735,423,1047,267,1515,
1183,52,1300,676,364,988,208,1456,832,520,1144,130,1378,754,442,1066,286,910,598,1222,13,1261,637,325,949,169,1417,793,481,1105,91,1339,715,403,1027,247,1495,871,559,
1310,686,374,998,218,1466,842,530,1154,140,1388,764,452,1076,296,920,608,1232,23,1271,647,335,959,179,1427,803,491,1115,101,1349,725,413,1037,257,1505,881,569,1193,62,
354,978,198,1446,822,510,1134,120,1368,744,432,1056,276,900,588,1212,1209,1251,627,315,939,159,1407,783,471,1095,81,1329,705,393,1017,237,1485,861,549,1173,42,1290,666,
230,1478,854,542,1166,152,1400,776,464,1088,308,932,620,1244,35,1283,659,347,971,191,1439,815,503,1127,113,1361,737,425,1049,269,1517,893,581,1205,74,1322,698,386,1010,
834,522,1146,132,1380,756,444,1068,288,912,600,1224,15,1263,639,327,951,171,1419,795,483,1107,93,1341,717,405,1029,249,1497,873,561,1185,54,1302,678,366,990,210,1458,
1156,142,1390,766,454,1078,298,922,610,1234,25,1273,649,337,961,181,1429,805,493,1117,103,1351,727,415,1039,259,1507,883,571,1195,64,1312,688,376,1000,220,1468,844,532,
1370,746,434,1058,278,902,590,1214,5,1253,629,317,941,161,1409,785,473,1097,83,1331,707,395,1019,239,1487,863,551,1175,44,1292,668,356,980,200,1448,824,512,1136,122,
459,1083,303,927,615,1239,30,1278,654,342,966,186,1434,810,498,1122,108,1356,732,420,1044,264,1512,888,576,1200,69,1317,693,381,1005,225,1473,849,537,1161,147,1395,771,
283,907,595,1219,10,1258,634,322,946,166,1414,790,478,1102,88,1336,712,400,1024,244,1492,868,556,1180,49,1297,673,361,985,205,1453,829,517,1141,127,1375,751,439,1063,
605,1229,20,1268,644,332,956,176,1424,800,488,1112,98,1346,722,410,1034,254,1502,878,566,1190,59,1307,683,371,995,215,1463,839,527,1151,137,1385,761,449,1073,293,917,
0,1248,624,312,936,156,1404,780,468,1092,78,1326,702,390,1014,234,1482,858,546,1170,39,1287,663,351,975,195,1443,819,507,1131,117,1365,741,429,1053,273,897,585,3
};
int tableh18[] = { /* 41 x 41 data */
2,332,1644,988,168,1480,824,496,1152,86,1398,742,414,1070,250,1562,906,578,1234,45,1357,701,373,1029,209,1521,865,537,1193,127,1439,783,455,1111,291,1603,947,619,1275,4,1,
1677,1021,201,1513,857,529,1185,119,1431,775,447,1103,283,1595,939,611,1267,78,1390,734,406,1062,242,1554,898,570,1226,160,1472,816,488,1144,324,1636,980,652,1308,37,1349,693,365,
181,1493,837,509,1165,99,1411,755,427,1083,263,1575,919,591,1247,58,1370,714,386,1042,222,1534,878,550,1206,140,1452,796,468,1124,304,1616,960,632,1288,17,1329,673,345,1657,1001,
847,519,1175,109,1421,765,437,1093,273,1585,929,601,1257,68,1380,724,396,1052,232,1544,888,560,1216,150,1462,806,478,1134,314,1626,970,642,1298,27,1339,683,355,1667,1011,191,1503,
1155,89,1401,745,417,1073,253,1565,909,581,1237,48,1360,704,376,1032,212,1524,868,540,1196,130,1442,786,458,1114,294,1606,950,622,1278,7,1319,663,335,1647,991,171,1483,827,499,
1426,770,442,1098,278,1590,934,606,1262,73,1385,729,401,1057,237,1549,893,565,1221,155,1467,811,483,1139,319,1631,975,647,1303,32,1344,688,360,1672,1016,196,1508,852,524,1180,114,
422,1078,258,1570,914,586,1242,53,1365,709,381,1037,217,1529,873,545,1201,135,1447,791,463,1119,299,1611,955,627,1283,12,1324,668,340,1652,996,176,1488,832,504,1160,94,1406,750,
268,1580,924,596,1252,63,1375,719,391,1047,227,1539,883,555,1211,145,1457,801,473,1129,309,1621,965,637,1293,22,1334,678,350,1662,1006,186,1498,842,514,1170,104,1416,760,432,1088,
903,575,1231,42,1354,698,370,1026,206,1518,862,534,1190,124,1436,780,452,1108,288,1600,944,616,1272,1316,1313,657,329,1641,985,165,1477,821,493,1149,83,1395,739,411,1067,247,1559,
1270,81,1393,737,409,1065,245,1557,901,573,1229,163,1475,819,491,1147,327,1639,983,655,1311,40,1352,696,368,1680,1024,204,1516,860,532,1188,122,1434,778,450,1106,286,1598,942,614,
1373,717,389,1045,225,1537,881,553,1209,143,1455,799,471,1127,307,1619,963,635,1291,20,1332,676,348,1660,1004,184,1496,840,512,1168,102,1414,758,430,1086,266,1578,922,594,1250,61,
399,1055,235,1547,891,563,1219,153,1465,809,481,1137,317,1629,973,645,1301,30,1342,686,358,1670,1014,194,1506,850,522,1178,112,1424,768,440,1096,276,1588,932,604,1260,71,1383,727,
215,1527,871,543,1199,133,1445,789,461,1117,297,1609,953,625,1281,10,1322,666,338,1650,994,174,1486,830,502,1158,92,1404,748,420,1076,256,1568,912,584,1240,51,1363,707,379,1035,
896,568,1224,158,1470,814,486,1142,322,1634,978,650,1306,35,1347,691,363,1675,1019,199,1511,855,527,1183,117,1429,773,445,1101,281,1593,937,609,1265,76,1388,732,404,1060,240,1552,
1204,138,1450,794,466,1122,302,1614,958,630,1286,15,1327,671,343,1655,999,179,1491,835,507,1163,97,1409,753,425,1081,261,1573,917,589,1245,56,1368,712,384,1040,220,1532,876,548,
1460,804,476,1132,312,1624,968,640,1296,25,1337,681,353,1665,1009,189,1501,845,517,1173,107,1419,763,435,1091,271,1583,927,599,1255,66,1378,722,394,1050,230,1542,886,558,1214,148,
456,1112,292,1604,948,620,1276,5,1317,661,333,1645,989,169,1481,825,497,1153,87,1399,743,415,1071,251,1563,907,579,1235,46,1358,702,374,1030,210,1522,866,538,1194,128,1440,784,
325,1637,981,653,1309,38,1350,694,366,1678,1022,202,1514,858,530,1186,120,1432,776,448,1104,284,1596,940,612,1268,79,1391,735,407,1063,243,1555,899,571,1227,161,1473,817,489,1145,
961,633,1289,18,1330,674,346,1658,1002,182,1494,838,510,1166,100,1412,756,428,1084,264,1576,920,592,1248,59,1371,715,387,1043,223,1535,879,551,1207,141,1453,797,469,1125,305,1617,
1299,28,1340,684,356,1668,1012,192,1504,848,520,1176,110,1422,766,438,1094,274,1586,930,602,1258,69,1381,725,397,1053,233,1545,889,561,1217,151,1463,807,479,1135,315,1627,971,643,
1320,664,336,1648,992,172,1484,828,500,1156,90,1402,746,418,1074,254,1566,910,582,1238,49,1361,705,377,1033,213,1525,869,541,1197,131,1443,787,459,1115,295,1607,951,623,1279,8,
361,1673,1017,197,1509,853,525,1181,115,1427,771,443,1099,279,1591,935,607,1263,74,1386,730,402,1058,238,1550,894,566,1222,156,1468,812,484,1140,320,1632,976,648,1304,33,1345,689,
997,177,1489,833,505,1161,95,1407,751,423,1079,259,1571,915,587,1243,54,1366,710,382,1038,218,1530,874,546,1202,136,1448,792,464,1120,300,1612,956,628,1284,13,1325,669,341,1653,
1499,843,515,1171,105,1417,761,433,1089,269,1581,925,597,1253,64,1376,720,392,1048,228,1540,884,556,1212,146,1458,802,474,1130,310,1622,966,638,1294,23,1335,679,351,1663,1007,187,
494,1150,84,1396,740,412,1068,248,1560,904,576,1232,43,1355,699,371,1027,207,1519,863,535,1191,125,1437,781,453,1109,289,1601,945,617,1273,660,1314,658,330,1642,986,166,1478,822,
121,1433,777,449,1105,285,1597,941,613,1269,80,1392,736,408,1064,244,1556,900,572,1228,162,1474,818,490,1146,326,1638,982,654,1310,39,1351,695,367,1679,1023,203,1515,859,531,1187,
757,429,1085,265,1577,921,593,1249,60,1372,716,388,1044,224,1536,880,552,1208,142,1454,798,470,1126,306,1618,962,634,1290,19,1331,675,347,1659,1003,183,1495,839,511,1167,101,1413,
1095,275,1587,931,603,1259,70,1382,726,398,1054,234,1546,890,562,1218,152,1464,808,480,1136,316,1628,972,644,1300,29,1341,685,357,1669,1013,193,1505,849,521,1177,111,1423,767,439,
1567,911,583,1239,50,1362,706,378,1034,214,1526,870,542,1198,132,1444,788,460,1116,296,1608,952,624,1280,9,1321,665,337,1649,993,173,1485,829,501,1157,91,1403,747,419,1075,255,
608,1264,75,1387,731,403,1059,239,1551,895,567,1223,157,1469,813,485,1141,321,1633,977,649,1305,34,1346,690,362,1674,1018,198,1510,854,526,1182,116,1428,772,444,1100,280,1592,936,
55,1367,711,383,1039,219,1531,875,547,1203,137,1449,793,465,1121,301,1613,957,629,1285,14,1326,670,342,1654,998,178,1490,834,506,1162,96,1408,752,424,1080,260,1572,916,588,1244,
721,393,1049,229,1541,885,557,1213,147,1459,803,475,1131,311,1623,967,639,1295,24,1336,680,352,1664,1008,188,1500,844,516,1172,106,1418,762,434,1090,270,1582,926,598,1254,65,1377,
1028,208,1520,864,536,1192,126,1438,782,454,1110,290,1602,946,618,1274,1271,1315,659,331,1643,987,167,1479,823,495,1151,85,1397,741,413,1069,249,1561,905,577,1233,44,1356,700,372,
1553,897,569,1225,159,1471,815,487,1143,323,1635,979,651,1307,36,1348,692,364,1676,1020,200,1512,856,528,1184,118,1430,774,446,1102,282,1594,938,610,1266,77,1389,733,405,1061,241,
549,1205,139,1451,795,467,1123,303,1615,959,631,1287,16,1328,672,344,1656,1000,180,1492,836,508,1164,98,1410,754,426,1082,262,1574,918,590,1246,57,1369,713,385,1041,221,1533,877,
149,1461,805,477,1133,313,1625,969,641,1297,26,1338,682,354,1666,1010,190,1502,846,518,1174,108,1420,764,436,1092,272,1584,928,600,1256,67,1379,723,395,1051,231,1543,887,559,1215,
785,457,1113,293,1605,949,621,1277,6,1318,662,334,1646,990,170,1482,826,498,1154,88,1400,744,416,1072,252,1564,908,580,1236,47,1359,703,375,1031,211,1523,867,539,1195,129,1441,
1138,318,1630,974,646,1302,31,1343,687,359,1671,1015,195,1507,851,523,1179,113,1425,769,441,1097,277,1589,933,605,1261,72,1384,728,400,1056,236,1548,892,564,1220,154,1466,810,482,
1610,954,626,1282,11,1323,667,339,1651,995,175,1487,831,503,1159,93,1405,749,421,1077,257,1569,913,585,1241,52,1364,708,380,1036,216,1528,872,544,1200,134,1446,790,462,1118,298,
636,1292,21,1333,677,349,1661,1005,185,1497,841,513,1169,103,1415,759,431,1087,267,1579,923,595,1251,62,1374,718,390,1046,226,1538,882,554,1210,144,1456,800,472,1128,308,1620,964,
0,1312,656,328,1640,984,164,1476,820,492,1148,82,1394,738,410,1066,246,1558,902,574,1230,41,1353,697,369,1025,205,1517,861,533,1189,123,1435,779,451,1107,287,1599,943,615,3
};
int tableh19[] = { /* 43 x 43 data */
2,359,1735,1047,187,1563,875,531,1219,101,1477,789,445,1821,1133,273,1649,961,617,1305,58,1434,746,402,1778,1090,230,1606,918,574,1262,144,1520,832,488,1176,316,1692,1004,660,1348,15,1,
1746,1058,198,1574,886,542,1230,112,1488,800,456,1832,1144,284,1660,972,628,1316,69,1445,757,413,1789,1101,241,1617,929,585,1273,155,1531,843,499,1187,327,1703,1015,671,1359,26,1402,714,370,
176,1552,864,520,1208,90,1466,778,434,1810,1122,262,1638,950,606,1294,47,1423,735,391,1767,1079,219,1595,907,563,1251,133,1509,821,477,1165,305,1681,993,649,1337,4,1380,692,348,1724,1036,
899,555,1243,125,1501,813,469,1845,1157,297,1673,985,641,1329,82,1458,770,426,1802,1114,254,1630,942,598,1286,168,1544,856,512,1200,340,1716,1028,684,1372,39,1415,727,383,1759,1071,211,1587,
1222,104,1480,792,448,1824,1136,276,1652,964,620,1308,61,1437,749,405,1781,1093,233,1609,921,577,1265,147,1523,835,491,1179,319,1695,1007,663,1351,18,1394,706,362,1738,1050,190,1566,878,534,
1491,803,459,1835,1147,287,1663,975,631,1319,72,1448,760,416,1792,1104,244,1620,932,588,1276,158,1534,846,502,1190,330,1706,1018,674,1362,29,1405,717,373,1749,1061,201,1577,889,545,1233,115,
437,1813,1125,265,1641,953,609,1297,50,1426,738,394,1770,1082,222,1598,910,566,1254,136,1512,824,480,1168,308,1684,996,652,1340,7,1383,695,351,1727,1039,179,1555,867,523,1211,93,1469,781,
1152,292,1668,980,636,1324,77,1453,765,421,1797,1109,249,1625,937,593,1281,163,1539,851,507,1195,335,1711,1023,679,1367,34,1410,722,378,1754,1066,206,1582,894,550,1238,120,1496,808,464,1840,
1646,958,614,1302,55,1431,743,399,1775,1087,227,1603,915,571,1259,141,1517,829,485,1173,313,1689,1001,657,1345,12,1388,700,356,1732,1044,184,1560,872,528,1216,98,1474,786,442,1818,1130,270,
625,1313,66,1442,754,410,1786,1098,238,1614,926,582,1270,152,1528,840,496,1184,324,1700,1012,668,1356,23,1399,711,367,1743,1055,195,1571,883,539,1227,109,1485,797,453,1829,1141,281,1657,969,
44,1420,732,388,1764,1076,216,1592,904,560,1248,130,1506,818,474,1162,302,1678,990,646,1334,1391,1377,689,345,1721,1033,173,1549,861,517,1205,87,1463,775,431,1807,1119,259,1635,947,603,1291,
773,429,1805,1117,257,1633,945,601,1289,171,1547,859,515,1203,343,1719,1031,687,1375,42,1418,730,386,1762,1074,214,1590,902,558,1246,128,1504,816,472,1848,1160,300,1676,988,644,1332,85,1461,
1784,1096,236,1612,924,580,1268,150,1526,838,494,1182,322,1698,1010,666,1354,21,1397,709,365,1741,1053,193,1569,881,537,1225,107,1483,795,451,1827,1139,279,1655,967,623,1311,64,1440,752,408,
247,1623,935,591,1279,161,1537,849,505,1193,333,1709,1021,677,1365,32,1408,720,376,1752,1064,204,1580,892,548,1236,118,1494,806,462,1838,1150,290,1666,978,634,1322,75,1451,763,419,1795,1107,
913,569,1257,139,1515,827,483,1171,311,1687,999,655,1343,10,1386,698,354,1730,1042,182,1558,870,526,1214,96,1472,784,440,1816,1128,268,1644,956,612,1300,53,1429,741,397,1773,1085,225,1601,
1284,166,1542,854,510,1198,338,1714,1026,682,1370,37,1413,725,381,1757,1069,209,1585,897,553,1241,123,1499,811,467,1843,1155,295,1671,983,639,1327,80,1456,768,424,1800,1112,252,1628,940,596,
1521,833,489,1177,317,1693,1005,661,1349,16,1392,704,360,1736,1048,188,1564,876,532,1220,102,1478,790,446,1822,1134,274,1650,962,618,1306,59,1435,747,403,1779,1091,231,1607,919,575,1263,145,
500,1188,328,1704,1016,672,1360,27,1403,715,371,1747,1059,199,1575,887,543,1231,113,1489,801,457,1833,1145,285,1661,973,629,1317,70,1446,758,414,1790,1102,242,1618,930,586,1274,156,1532,844,
306,1682,994,650,1338,5,1381,693,349,1725,1037,177,1553,865,521,1209,91,1467,779,435,1811,1123,263,1639,951,607,1295,48,1424,736,392,1768,1080,220,1596,908,564,1252,134,1510,822,478,1166,
1029,685,1373,40,1416,728,384,1760,1072,212,1588,900,556,1244,126,1502,814,470,1846,1158,298,1674,986,642,1330,83,1459,771,427,1803,1115,255,1631,943,599,1287,169,1545,857,513,1201,341,1717,
1352,19,1395,707,363,1739,1051,191,1567,879,535,1223,105,1481,793,449,1825,1137,277,1653,965,621,1309,62,1438,750,406,1782,1094,234,1610,922,578,1266,148,1524,836,492,1180,320,1696,1008,664,
1406,718,374,1750,1062,202,1578,890,546,1234,116,1492,804,460,1836,1148,288,1664,976,632,1320,73,1449,761,417,1793,1105,245,1621,933,589,1277,159,1535,847,503,1191,331,1707,1019,675,1363,30,
352,1728,1040,180,1556,868,524,1212,94,1470,782,438,1814,1126,266,1642,954,610,1298,51,1427,739,395,1771,1083,223,1599,911,567,1255,137,1513,825,481,1169,309,1685,997,653,1341,8,1384,696,
1067,207,1583,895,551,1239,121,1497,809,465,1841,1153,293,1669,981,637,1325,78,1454,766,422,1798,1110,250,1626,938,594,1282,164,1540,852,508,1196,336,1712,1024,680,1368,35,1411,723,379,1755,
1561,873,529,1217,99,1475,787,443,1819,1131,271,1647,959,615,1303,56,1432,744,400,1776,1088,228,1604,916,572,1260,142,1518,830,486,1174,314,1690,1002,658,1346,13,1389,701,357,1733,1045,185,
540,1228,110,1486,798,454,1830,1142,282,1658,970,626,1314,67,1443,755,411,1787,1099,239,1615,927,583,1271,153,1529,841,497,1185,325,1701,1013,669,1357,24,1400,712,368,1744,1056,196,1572,884,
88,1464,776,432,1808,1120,260,1636,948,604,1292,45,1421,733,389,1765,1077,217,1593,905,561,1249,131,1507,819,475,1163,303,1679,991,647,1335,703,1378,690,346,1722,1034,174,1550,862,518,1206,
815,471,1847,1159,299,1675,987,643,1331,84,1460,772,428,1804,1116,256,1632,944,600,1288,170,1546,858,514,1202,342,1718,1030,686,1374,41,1417,729,385,1761,1073,213,1589,901,557,1245,127,1503,
1826,1138,278,1654,966,622,1310,63,1439,751,407,1783,1095,235,1611,923,579,1267,149,1525,837,493,1181,321,1697,1009,665,1353,20,1396,708,364,1740,1052,192,1568,880,536,1224,106,1482,794,450,
289,1665,977,633,1321,74,1450,762,418,1794,1106,246,1622,934,590,1278,160,1536,848,504,1192,332,1708,1020,676,1364,31,1407,719,375,1751,1063,203,1579,891,547,1235,117,1493,805,461,1837,1149,
955,611,1299,52,1428,740,396,1772,1084,224,1600,912,568,1256,138,1514,826,482,1170,310,1686,998,654,1342,9,1385,697,353,1729,1041,181,1557,869,525,1213,95,1471,783,439,1815,1127,267,1643,
1326,79,1455,767,423,1799,1111,251,1627,939,595,1283,165,1541,853,509,1197,337,1713,1025,681,1369,36,1412,724,380,1756,1068,208,1584,896,552,1240,122,1498,810,466,1842,1154,294,1670,982,638,
1433,745,401,1777,1089,229,1605,917,573,1261,143,1519,831,487,1175,315,1691,1003,659,1347,14,1390,702,358,1734,1046,186,1562,874,530,1218,100,1476,788,444,1820,1132,272,1648,960,616,1304,57,
412,1788,1100,240,1616,928,584,1272,154,1530,842,498,1186,326,1702,1014,670,1358,25,1401,713,369,1745,1057,197,1573,885,541,1229,111,1487,799,455,1831,1143,283,1659,971,627,1315,68,1444,756,
1078,218,1594,906,562,1250,132,1508,820,476,1164,304,1680,992,648,1336,1333,1379,691,347,1723,1035,175,1551,863,519,1207,89,1465,777,433,1809,1121,261,1637,949,605,1293,46,1422,734,390,1766,
1629,941,597,1285,167,1543,855,511,1199,339,1715,1027,683,1371,38,1414,726,382,1758,1070,210,1586,898,554,1242,124,1500,812,468,1844,1156,296,1672,984,640,1328,81,1457,769,425,1801,1113,253,
576,1264,146,1522,834,490,1178,318,1694,1006,662,1350,17,1393,705,361,1737,1049,189,1565,877,533,1221,103,1479,791,447,1823,1135,275,1651,963,619,1307,60,1436,748,404,1780,1092,232,1608,920,
157,1533,845,501,1189,329,1705,1017,673,1361,28,1404,716,372,1748,1060,200,1576,888,544,1232,114,1490,802,458,1834,1146,286,1662,974,630,1318,71,1447,759,415,1791,1103,243,1619,931,587,1275,
823,479,1167,307,1683,995,651,1339,6,1382,694,350,1726,1038,178,1554,866,522,1210,92,1468,780,436,1812,1124,264,1640,952,608,1296,49,1425,737,393,1769,1081,221,1597,909,565,1253,135,1511,
1194,334,1710,1022,678,1366,33,1409,721,377,1753,1065,205,1581,893,549,1237,119,1495,807,463,1839,1151,291,1667,979,635,1323,76,1452,764,420,1796,1108,248,1624,936,592,1280,162,1538,850,506,
1688,1000,656,1344,11,1387,699,355,1731,1043,183,1559,871,527,1215,97,1473,785,441,1817,1129,269,1645,957,613,1301,54,1430,742,398,1774,1086,226,1602,914,570,1258,140,1516,828,484,1172,312,
667,1355,22,1398,710,366,1742,1054,194,1570,882,538,1226,108,1484,796,452,1828,1140,280,1656,968,624,1312,65,1441,753,409,1785,1097,237,1613,925,581,1269,151,1527,839,495,1183,323,1699,1011,
0,1376,688,344,1720,1032,172,1548,860,516,1204,86,1462,774,430,1806,1118,258,1634,946,602,1290,43,1419,731,387,1763,1075,215,1591,903,559,1247,129,1505,817,473,1161,301,1677,989,645,3
};
int tableh20[] = { /* 45 x 45 data */
2,370,1810,1090,190,1630,910,550,1990,1270,100,1540,820,460,1900,1180,280,1720,1000,640,1360,55,1495,775,415,1855,1135,235,1675,955,595,1315,145,1585,865,505,1945,1225,325,1765,1045,685,1405,10,1,
1838,1118,218,1658,938,578,2018,1298,128,1568,848,488,1928,1208,308,1748,1028,668,1388,83,1523,803,443,1883,1163,263,1703,983,623,1343,173,1613,893,533,1973,1253,353,1793,1073,713,1433,38,1478,758,398,
196,1636,916,556,1996,1276,106,1546,826,466,1906,1186,286,1726,1006,646,1366,61,1501,781,421,1861,1141,241,1681,961,601,1321,151,1591,871,511,1951,1231,331,1771,1051,691,1411,16,1456,736,376,1816,1096,
927,567,2007,1287,117,1557,837,477,1917,1197,297,1737,1017,657,1377,72,1512,792,432,1872,1152,252,1692,972,612,1332,162,1602,882,522,1962,1242,342,1782,1062,702,1422,27,1467,747,387,1827,1107,207,1647,
1984,1264,94,1534,814,454,1894,1174,274,1714,994,634,1354,49,1489,769,409,1849,1129,229,1669,949,589,1309,139,1579,859,499,1939,1219,319,1759,1039,679,1399,4,1444,724,364,1804,1084,184,1624,904,544,
131,1571,851,491,1931,1211,311,1751,1031,671,1391,86,1526,806,446,1886,1166,266,1706,986,626,1346,176,1616,896,536,1976,1256,356,1796,1076,716,1436,41,1481,761,401,1841,1121,221,1661,941,581,2021,1301,
829,469,1909,1189,289,1729,1009,649,1369,64,1504,784,424,1864,1144,244,1684,964,604,1324,154,1594,874,514,1954,1234,334,1774,1054,694,1414,19,1459,739,379,1819,1099,199,1639,919,559,1999,1279,109,1549,
1920,1200,300,1740,1020,660,1380,75,1515,795,435,1875,1155,255,1695,975,615,1335,165,1605,885,525,1965,1245,345,1785,1065,705,1425,30,1470,750,390,1830,1110,210,1650,930,570,2010,1290,120,1560,840,480,
277,1717,997,637,1357,52,1492,772,412,1852,1132,232,1672,952,592,1312,142,1582,862,502,1942,1222,322,1762,1042,682,1402,7,1447,727,367,1807,1087,187,1627,907,547,1987,1267,97,1537,817,457,1897,1177,
1025,665,1385,80,1520,800,440,1880,1160,260,1700,980,620,1340,170,1610,890,530,1970,1250,350,1790,1070,710,1430,35,1475,755,395,1835,1115,215,1655,935,575,2015,1295,125,1565,845,485,1925,1205,305,1745,
1363,58,1498,778,418,1858,1138,238,1678,958,598,1318,148,1588,868,508,1948,1228,328,1768,1048,688,1408,13,1453,733,373,1813,1093,193,1633,913,553,1993,1273,103,1543,823,463,1903,1183,283,1723,1003,643,
1509,789,429,1869,1149,249,1689,969,609,1329,159,1599,879,519,1959,1239,339,1779,1059,699,1419,24,1464,744,384,1824,1104,204,1644,924,564,2004,1284,114,1554,834,474,1914,1194,294,1734,1014,654,1374,69,
406,1846,1126,226,1666,946,586,1306,136,1576,856,496,1936,1216,316,1756,1036,676,1396,1450,1441,721,361,1801,1081,181,1621,901,541,1981,1261,91,1531,811,451,1891,1171,271,1711,991,631,1351,46,1486,766,
1169,269,1709,989,629,1349,179,1619,899,539,1979,1259,359,1799,1079,719,1439,44,1484,764,404,1844,1124,224,1664,944,584,2024,1304,134,1574,854,494,1934,1214,314,1754,1034,674,1394,89,1529,809,449,1889,
1687,967,607,1327,157,1597,877,517,1957,1237,337,1777,1057,697,1417,22,1462,742,382,1822,1102,202,1642,922,562,2002,1282,112,1552,832,472,1912,1192,292,1732,1012,652,1372,67,1507,787,427,1867,1147,247,
618,1338,168,1608,888,528,1968,1248,348,1788,1068,708,1428,33,1473,753,393,1833,1113,213,1653,933,573,2013,1293,123,1563,843,483,1923,1203,303,1743,1023,663,1383,78,1518,798,438,1878,1158,258,1698,978,
146,1586,866,506,1946,1226,326,1766,1046,686,1406,11,1451,731,371,1811,1091,191,1631,911,551,1991,1271,101,1541,821,461,1901,1181,281,1721,1001,641,1361,56,1496,776,416,1856,1136,236,1676,956,596,1316,
894,534,1974,1254,354,1794,1074,714,1434,39,1479,759,399,1839,1119,219,1659,939,579,2019,1299,129,1569,849,489,1929,1209,309,1749,1029,669,1389,84,1524,804,444,1884,1164,264,1704,984,624,1344,174,1614,
1952,1232,332,1772,1052,692,1412,17,1457,737,377,1817,1097,197,1637,917,557,1997,1277,107,1547,827,467,1907,1187,287,1727,1007,647,1367,62,1502,782,422,1862,1142,242,1682,962,602,1322,152,1592,872,512,
343,1783,1063,703,1423,28,1468,748,388,1828,1108,208,1648,928,568,2008,1288,118,1558,838,478,1918,1198,298,1738,1018,658,1378,73,1513,793,433,1873,1153,253,1693,973,613,1333,163,1603,883,523,1963,1243,
1040,680,1400,5,1445,725,365,1805,1085,185,1625,905,545,1985,1265,95,1535,815,455,1895,1175,275,1715,995,635,1355,50,1490,770,410,1850,1130,230,1670,950,590,1310,140,1580,860,500,1940,1220,320,1760,
1437,42,1482,762,402,1842,1122,222,1662,942,582,2022,1302,132,1572,852,492,1932,1212,312,1752,1032,672,1392,87,1527,807,447,1887,1167,267,1707,987,627,1347,177,1617,897,537,1977,1257,357,1797,1077,717,
1460,740,380,1820,1100,200,1640,920,560,2000,1280,110,1550,830,470,1910,1190,290,1730,1010,650,1370,65,1505,785,425,1865,1145,245,1685,965,605,1325,155,1595,875,515,1955,1235,335,1775,1055,695,1415,20,
391,1831,1111,211,1651,931,571,2011,1291,121,1561,841,481,1921,1201,301,1741,1021,661,1381,76,1516,796,436,1876,1156,256,1696,976,616,1336,166,1606,886,526,1966,1246,346,1786,1066,706,1426,31,1471,751,
1088,188,1628,908,548,1988,1268,98,1538,818,458,1898,1178,278,1718,998,638,1358,53,1493,773,413,1853,1133,233,1673,953,593,1313,143,1583,863,503,1943,1223,323,1763,1043,683,1403,8,1448,728,368,1808,
1656,936,576,2016,1296,126,1566,846,486,1926,1206,306,1746,1026,666,1386,81,1521,801,441,1881,1161,261,1701,981,621,1341,171,1611,891,531,1971,1251,351,1791,1071,711,1431,36,1476,756,396,1836,1116,216,
554,1994,1274,104,1544,824,464,1904,1184,284,1724,1004,644,1364,59,1499,779,419,1859,1139,239,1679,959,599,1319,149,1589,869,509,1949,1229,329,1769,1049,689,1409,14,1454,734,374,1814,1094,194,1634,914,
1285,115,1555,835,475,1915,1195,295,1735,1015,655,1375,70,1510,790,430,1870,1150,250,1690,970,610,1330,160,1600,880,520,1960,1240,340,1780,1060,700,1420,25,1465,745,385,1825,1105,205,1645,925,565,2005,
1532,812,452,1892,1172,272,1712,992,632,1352,47,1487,767,407,1847,1127,227,1667,947,587,1307,137,1577,857,497,1937,1217,317,1757,1037,677,1397,730,1442,722,362,1802,1082,182,1622,902,542,1982,1262,92,
493,1933,1213,313,1753,1033,673,1393,88,1528,808,448,1888,1168,268,1708,988,628,1348,178,1618,898,538,1978,1258,358,1798,1078,718,1438,43,1483,763,403,1843,1123,223,1663,943,583,2023,1303,133,1573,853,
1191,291,1731,1011,651,1371,66,1506,786,426,1866,1146,246,1686,966,606,1326,156,1596,876,516,1956,1236,336,1776,1056,696,1416,21,1461,741,381,1821,1101,201,1641,921,561,2001,1281,111,1551,831,471,1911,
1742,1022,662,1382,77,1517,797,437,1877,1157,257,1697,977,617,1337,167,1607,887,527,1967,1247,347,1787,1067,707,1427,32,1472,752,392,1832,1112,212,1652,932,572,2012,1292,122,1562,842,482,1922,1202,302,
639,1359,54,1494,774,414,1854,1134,234,1674,954,594,1314,144,1584,864,504,1944,1224,324,1764,1044,684,1404,9,1449,729,369,1809,1089,189,1629,909,549,1989,1269,99,1539,819,459,1899,1179,279,1719,999,
82,1522,802,442,1882,1162,262,1702,982,622,1342,172,1612,892,532,1972,1252,352,1792,1072,712,1432,37,1477,757,397,1837,1117,217,1657,937,577,2017,1297,127,1567,847,487,1927,1207,307,1747,1027,667,1387,
780,420,1860,1140,240,1680,960,600,1320,150,1590,870,510,1950,1230,330,1770,1050,690,1410,15,1455,735,375,1815,1095,195,1635,915,555,1995,1275,105,1545,825,465,1905,1185,285,1725,1005,645,1365,60,1500,
1871,1151,251,1691,971,611,1331,161,1601,881,521,1961,1241,341,1781,1061,701,1421,26,1466,746,386,1826,1106,206,1646,926,566,2006,1286,116,1556,836,476,1916,1196,296,1736,1016,656,1376,71,1511,791,431,
228,1668,948,588,1308,138,1578,858,498,1938,1218,318,1758,1038,678,1398,1395,1443,723,363,1803,1083,183,1623,903,543,1983,1263,93,1533,813,453,1893,1173,273,1713,993,633,1353,48,1488,768,408,1848,1128,
985,625,1345,175,1615,895,535,1975,1255,355,1795,1075,715,1435,40,1480,760,400,1840,1120,220,1660,940,580,2020,1300,130,1570,850,490,1930,1210,310,1750,1030,670,1390,85,1525,805,445,1885,1165,265,1705,
1323,153,1593,873,513,1953,1233,333,1773,1053,693,1413,18,1458,738,378,1818,1098,198,1638,918,558,1998,1278,108,1548,828,468,1908,1188,288,1728,1008,648,1368,63,1503,783,423,1863,1143,243,1683,963,603,
1604,884,524,1964,1244,344,1784,1064,704,1424,29,1469,749,389,1829,1109,209,1649,929,569,2009,1289,119,1559,839,479,1919,1199,299,1739,1019,659,1379,74,1514,794,434,1874,1154,254,1694,974,614,1334,164,
501,1941,1221,321,1761,1041,681,1401,6,1446,726,366,1806,1086,186,1626,906,546,1986,1266,96,1536,816,456,1896,1176,276,1716,996,636,1356,51,1491,771,411,1851,1131,231,1671,951,591,1311,141,1581,861,
1249,349,1789,1069,709,1429,34,1474,754,394,1834,1114,214,1654,934,574,2014,1294,124,1564,844,484,1924,1204,304,1744,1024,664,1384,79,1519,799,439,1879,1159,259,1699,979,619,1339,169,1609,889,529,1969,
1767,1047,687,1407,12,1452,732,372,1812,1092,192,1632,912,552,1992,1272,102,1542,822,462,1902,1182,282,1722,1002,642,1362,57,1497,777,417,1857,1137,237,1677,957,597,1317,147,1587,867,507,1947,1227,327,
698,1418,23,1463,743,383,1823,1103,203,1643,923,563,2003,1283,113,1553,833,473,1913,1193,293,1733,1013,653,1373,68,1508,788,428,1868,1148,248,1688,968,608,1328,158,1598,878,518,1958,1238,338,1778,1058,
0,1440,720,360,1800,1080,180,1620,900,540,1980,1260,90,1530,810,450,1890,1170,270,1710,990,630,1350,45,1485,765,405,1845,1125,225,1665,945,585,1305,135,1575,855,495,1935,1215,315,1755,1035,675,3
};
int tableh21[] = { /* 47 x 47 data */
2,398,1902,1150,210,1714,962,586,2090,1338,116,1620,868,492,1996,1244,304,1808,1056,680,2184,1432,69,1573,821,445,1949,1197,257,1761,1009,633,2137,1385,163,1667,915,539,2043,1291,351,1855,1103,727,1479,22,1,
1914,1162,222,1726,974,598,2102,1350,128,1632,880,504,2008,1256,316,1820,1068,692,2196,1444,81,1585,833,457,1961,1209,269,1773,1021,645,2149,1397,175,1679,927,551,2055,1303,363,1867,1115,739,1491,34,1538,786,410,
198,1702,950,574,2078,1326,104,1608,856,480,1984,1232,292,1796,1044,668,2172,1420,57,1561,809,433,1937,1185,245,1749,997,621,2125,1373,151,1655,903,527,2031,1279,339,1843,1091,715,1467,10,1514,762,386,1890,1138,
980,604,2108,1356,134,1638,886,510,2014,1262,322,1826,1074,698,2202,1450,87,1591,839,463,1967,1215,275,1779,1027,651,2155,1403,181,1685,933,557,2061,1309,369,1873,1121,745,1497,40,1544,792,416,1920,1168,228,1732,
2084,1332,110,1614,862,486,1990,1238,298,1802,1050,674,2178,1426,63,1567,815,439,1943,1191,251,1755,1003,627,2131,1379,157,1661,909,533,2037,1285,345,1849,1097,721,1473,16,1520,768,392,1896,1144,204,1708,956,580,
122,1626,874,498,2002,1250,310,1814,1062,686,2190,1438,75,1579,827,451,1955,1203,263,1767,1015,639,2143,1391,169,1673,921,545,2049,1297,357,1861,1109,733,1485,28,1532,780,404,1908,1156,216,1720,968,592,2096,1344,
850,474,1978,1226,286,1790,1038,662,2166,1414,51,1555,803,427,1931,1179,239,1743,991,615,2119,1367,145,1649,897,521,2025,1273,333,1837,1085,709,1461,4,1508,756,380,1884,1132,192,1696,944,568,2072,1320,98,1602,
2017,1265,325,1829,1077,701,2205,1453,90,1594,842,466,1970,1218,278,1782,1030,654,2158,1406,184,1688,936,560,2064,1312,372,1876,1124,748,1500,43,1547,795,419,1923,1171,231,1735,983,607,2111,1359,137,1641,889,513,
301,1805,1053,677,2181,1429,66,1570,818,442,1946,1194,254,1758,1006,630,2134,1382,160,1664,912,536,2040,1288,348,1852,1100,724,1476,19,1523,771,395,1899,1147,207,1711,959,583,2087,1335,113,1617,865,489,1993,1241,
1065,689,2193,1441,78,1582,830,454,1958,1206,266,1770,1018,642,2146,1394,172,1676,924,548,2052,1300,360,1864,1112,736,1488,31,1535,783,407,1911,1159,219,1723,971,595,2099,1347,125,1629,877,501,2005,1253,313,1817,
2169,1417,54,1558,806,430,1934,1182,242,1746,994,618,2122,1370,148,1652,900,524,2028,1276,336,1840,1088,712,1464,7,1511,759,383,1887,1135,195,1699,947,571,2075,1323,101,1605,853,477,1981,1229,289,1793,1041,665,
84,1588,836,460,1964,1212,272,1776,1024,648,2152,1400,178,1682,930,554,2058,1306,366,1870,1118,742,1494,37,1541,789,413,1917,1165,225,1729,977,601,2105,1353,131,1635,883,507,2011,1259,319,1823,1071,695,2199,1447,
812,436,1940,1188,248,1752,1000,624,2128,1376,154,1658,906,530,2034,1282,342,1846,1094,718,1470,13,1517,765,389,1893,1141,201,1705,953,577,2081,1329,107,1611,859,483,1987,1235,295,1799,1047,671,2175,1423,60,1564,
1952,1200,260,1764,1012,636,2140,1388,166,1670,918,542,2046,1294,354,1858,1106,730,1482,25,1529,777,401,1905,1153,213,1717,965,589,2093,1341,119,1623,871,495,1999,1247,307,1811,1059,683,2187,1435,72,1576,824,448,
236,1740,988,612,2116,1364,142,1646,894,518,2022,1270,330,1834,1082,706,1458,1526,1505,753,377,1881,1129,189,1693,941,565,2069,1317,95,1599,847,471,1975,1223,283,1787,1035,659,2163,1411,48,1552,800,424,1928,1176,
1033,657,2161,1409,187,1691,939,563,2067,1315,375,1879,1127,751,1503,46,1550,798,422,1926,1174,234,1738,986,610,2114,1362,140,1644,892,516,2020,1268,328,1832,1080,704,2208,1456,93,1597,845,469,1973,1221,281,1785,
2138,1386,164,1668,916,540,2044,1292,352,1856,1104,728,1480,23,1527,775,399,1903,1151,211,1715,963,587,2091,1339,117,1621,869,493,1997,1245,305,1809,1057,681,2185,1433,70,1574,822,446,1950,1198,258,1762,1010,634,
176,1680,928,552,2056,1304,364,1868,1116,740,1492,35,1539,787,411,1915,1163,223,1727,975,599,2103,1351,129,1633,881,505,2009,1257,317,1821,1069,693,2197,1445,82,1586,834,458,1962,1210,270,1774,1022,646,2150,1398,
904,528,2032,1280,340,1844,1092,716,1468,11,1515,763,387,1891,1139,199,1703,951,575,2079,1327,105,1609,857,481,1985,1233,293,1797,1045,669,2173,1421,58,1562,810,434,1938,1186,246,1750,998,622,2126,1374,152,1656,
2062,1310,370,1874,1122,746,1498,41,1545,793,417,1921,1169,229,1733,981,605,2109,1357,135,1639,887,511,2015,1263,323,1827,1075,699,2203,1451,88,1592,840,464,1968,1216,276,1780,1028,652,2156,1404,182,1686,934,558,
346,1850,1098,722,1474,17,1521,769,393,1897,1145,205,1709,957,581,2085,1333,111,1615,863,487,1991,1239,299,1803,1051,675,2179,1427,64,1568,816,440,1944,1192,252,1756,1004,628,2132,1380,158,1662,910,534,2038,1286,
1110,734,1486,29,1533,781,405,1909,1157,217,1721,969,593,2097,1345,123,1627,875,499,2003,1251,311,1815,1063,687,2191,1439,76,1580,828,452,1956,1204,264,1768,1016,640,2144,1392,170,1674,922,546,2050,1298,358,1862,
1462,5,1509,757,381,1885,1133,193,1697,945,569,2073,1321,99,1603,851,475,1979,1227,287,1791,1039,663,2167,1415,52,1556,804,428,1932,1180,240,1744,992,616,2120,1368,146,1650,898,522,2026,1274,334,1838,1086,710,
1548,796,420,1924,1172,232,1736,984,608,2112,1360,138,1642,890,514,2018,1266,326,1830,1078,702,2206,1454,91,1595,843,467,1971,1219,279,1783,1031,655,2159,1407,185,1689,937,561,2065,1313,373,1877,1125,749,1501,44,
396,1900,1148,208,1712,960,584,2088,1336,114,1618,866,490,1994,1242,302,1806,1054,678,2182,1430,67,1571,819,443,1947,1195,255,1759,1007,631,2135,1383,161,1665,913,537,2041,1289,349,1853,1101,725,1477,20,1524,772,
1160,220,1724,972,596,2100,1348,126,1630,878,502,2006,1254,314,1818,1066,690,2194,1442,79,1583,831,455,1959,1207,267,1771,1019,643,2147,1395,173,1677,925,549,2053,1301,361,1865,1113,737,1489,32,1536,784,408,1912,
1700,948,572,2076,1324,102,1606,854,478,1982,1230,290,1794,1042,666,2170,1418,55,1559,807,431,1935,1183,243,1747,995,619,2123,1371,149,1653,901,525,2029,1277,337,1841,1089,713,1465,8,1512,760,384,1888,1136,196,
602,2106,1354,132,1636,884,508,2012,1260,320,1824,1072,696,2200,1448,85,1589,837,461,1965,1213,273,1777,1025,649,2153,1401,179,1683,931,555,2059,1307,367,1871,1119,743,1495,38,1542,790,414,1918,1166,226,1730,978,
1330,108,1612,860,484,1988,1236,296,1800,1048,672,2176,1424,61,1565,813,437,1941,1189,249,1753,1001,625,2129,1377,155,1659,907,531,2035,1283,343,1847,1095,719,1471,14,1518,766,390,1894,1142,202,1706,954,578,2082,
1624,872,496,2000,1248,308,1812,1060,684,2188,1436,73,1577,825,449,1953,1201,261,1765,1013,637,2141,1389,167,1671,919,543,2047,1295,355,1859,1107,731,1483,26,1530,778,402,1906,1154,214,1718,966,590,2094,1342,120,
472,1976,1224,284,1788,1036,660,2164,1412,49,1553,801,425,1929,1177,237,1741,989,613,2117,1365,143,1647,895,519,2023,1271,331,1835,1083,707,1459,774,1506,754,378,1882,1130,190,1694,942,566,2070,1318,96,1600,848,
1267,327,1831,1079,703,2207,1455,92,1596,844,468,1972,1220,280,1784,1032,656,2160,1408,186,1690,938,562,2066,1314,374,1878,1126,750,1502,45,1549,797,421,1925,1173,233,1737,985,609,2113,1361,139,1643,891,515,2019,
1807,1055,679,2183,1431,68,1572,820,444,1948,1196,256,1760,1008,632,2136,1384,162,1666,914,538,2042,1290,350,1854,1102,726,1478,21,1525,773,397,1901,1149,209,1713,961,585,2089,1337,115,1619,867,491,1995,1243,303,
691,2195,1443,80,1584,832,456,1960,1208,268,1772,1020,644,2148,1396,174,1678,926,550,2054,1302,362,1866,1114,738,1490,33,1537,785,409,1913,1161,221,1725,973,597,2101,1349,127,1631,879,503,2007,1255,315,1819,1067,
1419,56,1560,808,432,1936,1184,244,1748,996,620,2124,1372,150,1654,902,526,2030,1278,338,1842,1090,714,1466,9,1513,761,385,1889,1137,197,1701,949,573,2077,1325,103,1607,855,479,1983,1231,291,1795,1043,667,2171,
1590,838,462,1966,1214,274,1778,1026,650,2154,1402,180,1684,932,556,2060,1308,368,1872,1120,744,1496,39,1543,791,415,1919,1167,227,1731,979,603,2107,1355,133,1637,885,509,2013,1261,321,1825,1073,697,2201,1449,86,
438,1942,1190,250,1754,1002,626,2130,1378,156,1660,908,532,2036,1284,344,1848,1096,720,1472,15,1519,767,391,1895,1143,203,1707,955,579,2083,1331,109,1613,861,485,1989,1237,297,1801,1049,673,2177,1425,62,1566,814,
1202,262,1766,1014,638,2142,1390,168,1672,920,544,2048,1296,356,1860,1108,732,1484,27,1531,779,403,1907,1155,215,1719,967,591,2095,1343,121,1625,873,497,2001,1249,309,1813,1061,685,2189,1437,74,1578,826,450,1954,
1742,990,614,2118,1366,144,1648,896,520,2024,1272,332,1836,1084,708,1460,1457,1507,755,379,1883,1131,191,1695,943,567,2071,1319,97,1601,849,473,1977,1225,285,1789,1037,661,2165,1413,50,1554,802,426,1930,1178,238,
653,2157,1405,183,1687,935,559,2063,1311,371,1875,1123,747,1499,42,1546,794,418,1922,1170,230,1734,982,606,2110,1358,136,1640,888,512,2016,1264,324,1828,1076,700,2204,1452,89,1593,841,465,1969,1217,277,1781,1029,
1381,159,1663,911,535,2039,1287,347,1851,1099,723,1475,18,1522,770,394,1898,1146,206,1710,958,582,2086,1334,112,1616,864,488,1992,1240,300,1804,1052,676,2180,1428,65,1569,817,441,1945,1193,253,1757,1005,629,2133,
1675,923,547,2051,1299,359,1863,1111,735,1487,30,1534,782,406,1910,1158,218,1722,970,594,2098,1346,124,1628,876,500,2004,1252,312,1816,1064,688,2192,1440,77,1581,829,453,1957,1205,265,1769,1017,641,2145,1393,171,
523,2027,1275,335,1839,1087,711,1463,6,1510,758,382,1886,1134,194,1698,946,570,2074,1322,100,1604,852,476,1980,1228,288,1792,1040,664,2168,1416,53,1557,805,429,1933,1181,241,1745,993,617,2121,1369,147,1651,899,
1305,365,1869,1117,741,1493,36,1540,788,412,1916,1164,224,1728,976,600,2104,1352,130,1634,882,506,2010,1258,318,1822,1070,694,2198,1446,83,1587,835,459,1963,1211,271,1775,1023,647,2151,1399,177,1681,929,553,2057,
1845,1093,717,1469,12,1516,764,388,1892,1140,200,1704,952,576,2080,1328,106,1610,858,482,1986,1234,294,1798,1046,670,2174,1422,59,1563,811,435,1939,1187,247,1751,999,623,2127,1375,153,1657,905,529,2033,1281,341,
729,1481,24,1528,776,400,1904,1152,212,1716,964,588,2092,1340,118,1622,870,494,1998,1246,306,1810,1058,682,2186,1434,71,1575,823,447,1951,1199,259,1763,1011,635,2139,1387,165,1669,917,541,2045,1293,353,1857,1105,
0,1504,752,376,1880,1128,188,1692,940,564,2068,1316,94,1598,846,470,1974,1222,282,1786,1034,658,2162,1410,47,1551,799,423,1927,1175,235,1739,987,611,2115,1363,141,1645,893,517,2021,1269,329,1833,1081,705,3
};
int MatrixMaxCapacities[21] = { 49, 81, 121, 169, 225, 289, 361, 441, 529, 625, 729, 841, 961, 1089, 1225, 1369, 1521, 1681, 1849, 2025, 2209 };
int MasterRandomStream[] = { /* From Annex L */
0x05,0xff,0xc7,0x31,0x88,0xa8,0x83,0x9c,0x64,0x87,0x9f,0x64,0xb3,0xe0,0x4d,0x9c,0x80,0x29,0x3a,0x90,
0xb3,0x8b,0x9e,0x90,0x45,0xbf,0xf5,0x68,0x4b,0x08,0xcf,0x44,0xb8,0xd4,0x4c,0x5b,0xa0,0xab,0x72,0x52,
0x1c,0xe4,0xd2,0x74,0xa4,0xda,0x8a,0x08,0xfa,0xa7,0xc7,0xdd,0x00,0x30,0xa9,0xe6,0x64,0xab,0xd5,0x8b,
0xed,0x9c,0x79,0xf8,0x08,0xd1,0x8b,0xc6,0x22,0x64,0x0b,0x33,0x43,0xd0,0x80,0xd4,0x44,0x95,0x2e,0x6f,
0x5e,0x13,0x8d,0x47,0x62,0x06,0xeb,0x80,0x82,0xc9,0x41,0xd5,0x73,0x8a,0x30,0x23,0x24,0xe3,0x7f,0xb2,
0xa8,0x0b,0xed,0x38,0x42,0x4c,0xd7,0xb0,0xce,0x98,0xbd,0xe1,0xd5,0xe4,0xc3,0x1d,0x15,0x4a,0xcf,0xd1,
0x1f,0x39,0x26,0x18,0x93,0xfc,0x19,0xb2,0x2d,0xab,0xf2,0x6e,0xa1,0x9f,0xaf,0xd0,0x8a,0x2b,0xa0,0x56,
0xb0,0x41,0x6d,0x43,0xa4,0x63,0xf3,0xaa,0x7d,0xaf,0x35,0x57,0xc2,0x94,0x4a,0x65,0x0b,0x41,0xde,0xb8,
0xe2,0x30,0x12,0x27,0x9b,0x66,0x2b,0x34,0x5b,0xb8,0x99,0xe8,0x28,0x71,0xd0,0x95,0x6b,0x07,0x4d,0x3c,
0x7a,0xb3,0xe5,0x29,0xb3,0xba,0x8c,0xcc,0x2d,0xe0,0xc9,0xc0,0x22,0xec,0x4c,0xde,0xf8,0x58,0x07,0xfc,
0x19,0xf2,0x64,0xe2,0xc3,0xe2,0xd8,0xb9,0xfd,0x67,0xa0,0xbc,0xf5,0x2e,0xc9,0x49,0x75,0x62,0x82,0x27,
0x10,0xf4,0x19,0x6f,0x49,0xf7,0xb3,0x84,0x14,0xea,0xeb,0xe1,0x2a,0x31,0xab,0x47,0x7d,0x08,0x29,0xac,
0xbb,0x72,0xfa,0xfa,0x62,0xb8,0xc8,0xd3,0x86,0x89,0x95,0xfd,0xdf,0xcc,0x9c,0xad,0xf1,0xd4,0x6c,0x64,
0x23,0x24,0x2a,0x56,0x1f,0x36,0xeb,0xb7,0xd6,0xff,0xda,0x57,0xf4,0x50,0x79,0x08,0x00
};

57
backend/font.h Normal file
View file

@ -0,0 +1,57 @@
/* font.h - Font for PNG images */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* This file contains the pixel-by-pixel representation of the "Misc Fixed" font
at 10 point size processed by the Gimp */
static int ascii_font[9310] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static int ascii_ext_font[9310] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0
};

7467
backend/gb2312.h Normal file

File diff suppressed because it is too large Load diff

1089
backend/gridmtx.c Normal file

File diff suppressed because it is too large Load diff

160
backend/gridmtx.h Normal file
View file

@ -0,0 +1,160 @@
/* gridmtx.h - definitions for Grid Matrix
libzint - the open source barcode library
Copyright (C) 2009 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define GM_NUMBER 1
#define GM_LOWER 2
#define GM_UPPER 3
#define GM_MIXED 4
#define GM_CONTROL 5
#define GM_BYTE 6
#define GM_CHINESE 7
#define EUROPIUM "0123456789ABCDEFGHIJKLMOPRSTUVWXYZabcdefghijklmnopqrstuvwxyz "
static char shift_set[] = {
/* From Table 7 - Encoding of control characters */
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* NULL -> SI */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* DLE -> US */
'!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':',
';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~'
};
static int gm_recommend_cw[] = { 9, 30, 59, 114, 170, 237, 315, 405, 506, 618, 741, 875, 1021 };
static int gm_max_cw[] = { 11, 40, 79, 146, 218, 305, 405, 521, 650, 794, 953, 1125, 1313 };
static int gm_total_cw[] = { 18, 50, 98, 162, 242, 338, 450, 578, 722, 882, 1058, 1250, 1458 };
static int gm_data_codewords[] = {
0, 15, 13, 11, 9,
45, 40, 35, 30, 25,
89, 79, 69, 59, 49,
146, 130, 114, 98, 81,
218, 194, 170, 146, 121,
305, 271, 237, 203, 169,
405, 360, 315, 270, 225,
521, 463, 405, 347, 289,
650, 578, 506, 434, 361,
794, 706, 618, 530, 441,
953, 847, 741, 635, 529,
1125, 1000, 875, 750, 625,
1313, 1167, 1021, 875, 729
};
static int gm_n1[] = { 18, 50, 98, 81, 121, 113, 113, 116, 121, 126, 118, 125, 122 };
static int gm_b1[] = { 1, 1, 1, 2, 2, 2, 2, 3, 2, 7, 5, 10, 6 };
static int gm_b2[] = { 0, 0, 0, 0, 0, 1, 2, 2, 4, 0, 4, 0, 6 };
static int gm_ebeb[] = {
/* E1 B3 E2 B4 */
0, 0, 0, 0, // version 1
3, 1, 0, 0,
5, 1, 0, 0,
7, 1, 0, 0,
9, 1, 0, 0,
5, 1, 0, 0, // version 2
10, 1, 0, 0,
15, 1, 0, 0,
20, 1, 0, 0,
25, 1, 0, 0,
9, 1, 0, 0, // version 3
19, 1, 0, 0,
29, 1, 0, 0,
39, 1, 0, 0,
49, 1, 0, 0,
8, 2, 0, 0, // version 4
16, 2, 0, 0,
24, 2, 0, 0,
32, 2, 0, 0,
41, 1, 10, 1,
12, 2, 0, 0, // version 5
24, 2, 0, 0,
36, 2, 0, 0,
48, 2, 0, 0,
61, 1, 60, 1,
11, 3, 0, 0, // version 6
23, 1, 22, 2,
34, 2, 33, 1,
45, 3, 0, 0,
57, 1, 56, 2,
12, 1, 11, 3, // version 7
23, 2, 22, 2,
34, 3, 33, 1,
45, 4, 0, 0,
57, 1, 56, 3,
12, 2, 11, 3, // version 8
23, 5, 0, 0,
35, 3, 34, 2,
47, 1, 46, 4,
58, 4, 57, 1,
12, 6, 0, 0, // version 9
24, 6, 0, 0,
36, 6, 0, 0,
48, 6, 0, 0,
61, 1, 60, 5,
13, 4, 12, 3, // version 10
26, 1, 25, 6,
38, 5, 37, 2,
51, 2, 50, 5,
63, 7, 0, 0,
12, 6, 11, 3, // version 11
24, 4, 23, 5,
36, 2, 35, 7,
47, 9, 0, 0,
59, 7, 58, 2,
13, 5, 12, 5, // version 12
25, 10, 0, 0,
38, 5, 37, 5,
50, 10, 0, 0,
63, 5, 62, 5,
13, 1, 12, 11, //version 13
25, 3, 24, 9,
37, 5, 36, 7,
49, 7, 48, 5,
61, 9, 60, 3
};
static int gm_macro_matrix[] = {
728,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,
727,624,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,651,
726,623,528,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,553,652,
725,622,527,440,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,463,554,653,
724,621,526,439,360,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,381,464,555,654,
723,620,525,438,359,288,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,307,382,465,556,655,
722,619,524,437,358,287,224,169,170,171,172,173,174,175,176,177,178,179,180,181,182,241,308,383,466,557,656,
721,618,523,436,357,286,223,168,121,122,123,124,125,126,127,128,129,130,131,132,183,242,309,384,467,558,657,
720,617,522,435,356,285,222,167,120,81,82,83,84,85,86,87,88,89,90,133,184,243,310,385,468,559,658,
719,616,521,434,355,284,221,166,119,80,49,50,51,52,53,54,55,56,91,134,185,244,311,386,469,560,659,
718,615,520,433,354,283,220,165,118,79,48,25,26,27,28,29,30,57,92,135,186,245,312,387,470,561,660,
717,614,519,432,353,282,219,164,117,78,47,24,9,10,11,12,31,58,93,136,187,246,313,388,471,562,661,
716,613,518,431,352,281,218,163,116,77,46,23,8,1,2,13,32,59,94,137,188,247,314,389,472,563,662,
715,612,517,430,351,280,217,162,115,76,45,22,7,0,3,14,33,60,95,138,189,248,315,390,473,564,663,
714,611,516,429,350,279,216,161,114,75,44,21,6,5,4,15,34,61,96,139,190,249,316,391,474,565,664,
713,610,515,428,349,278,215,160,113,74,43,20,19,18,17,16,35,62,97,140,191,250,317,392,475,566,665,
712,609,514,427,348,277,214,159,112,73,42,41,40,39,38,37,36,63,98,141,192,251,318,393,476,567,666,
711,608,513,426,347,276,213,158,111,72,71,70,69,68,67,66,65,64,99,142,193,252,319,394,477,568,667,
710,607,512,425,346,275,212,157,110,109,108,107,106,105,104,103,102,101,100,143,194,253,320,395,478,569,668,
709,606,511,424,345,274,211,156,155,154,153,152,151,150,149,148,147,146,145,144,195,254,321,396,479,570,669,
708,605,510,423,344,273,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,255,322,397,480,571,670,
707,604,509,422,343,272,271,270,269,268,267,266,265,264,263,262,261,260,259,258,257,256,323,398,481,572,671,
706,603,508,421,342,341,340,339,338,337,336,335,334,333,332,331,330,329,328,327,326,325,324,399,482,573,672,
705,602,507,420,419,418,417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,401,400,483,574,673,
704,601,506,505,504,503,502,501,500,499,498,497,496,495,494,493,492,491,490,489,488,487,486,485,484,575,674,
703,600,599,598,597,596,595,594,593,592,591,590,589,588,587,586,585,584,583,582,581,580,579,578,577,576,675,
702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685,684,683,682,681,680,679,678,677,676,
};

287
backend/gs1.c Normal file
View file

@ -0,0 +1,287 @@
/* gs1.c - Verifies GS1 data */
/*
libzint - the open source barcode library
Copyright (C) 2009 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef _MSC_VER
#include <malloc.h>
#endif
#include "common.h"
#include "gs1.h"
/* This code does some checks on the integrity of GS1 data. It is not intended
to be bulletproof, nor does it report very accurately what problem was found
or where, but should prevent some of the more common encoding errors */
void itostr(char ai_string[], int ai_value)
{
int thou, hund, ten, unit;
char temp[2];
strcpy(ai_string, "(");
thou = ai_value / 1000;
hund = (ai_value - (1000 * thou)) / 100;
ten = (ai_value - ((1000 * thou) + (100 * hund))) / 10;
unit = ai_value - ((1000 * thou) + (100 * hund) + (10 * ten));
temp[1] = '\0';
if(ai_value >= 1000) { temp[0] = itoc(thou); concat(ai_string, temp); }
if(ai_value >= 100) { temp[0] = itoc(hund); concat(ai_string, temp); }
temp[0] = itoc(ten);
concat(ai_string, temp);
temp[0] = itoc(unit);
concat(ai_string, temp);
concat(ai_string, ")");
}
int gs1_verify(struct zint_symbol *symbol, unsigned char source[], const unsigned int src_len, char reduced[])
{
int i, j, last_ai, ai_latch;
char ai_string[6];
int bracket_level, max_bracket_level, ai_length, max_ai_length, min_ai_length;
int ai_value[100], ai_location[100], ai_count, data_location[100], data_length[100];
int error_latch;
/* Detect extended ASCII characters */
for(i = 0; i < src_len; i++) {
if(source[i] >=128) {
strcpy(symbol->errtxt, "Extended ASCII characters are not supported by GS1");
return ERROR_INVALID_DATA;
}
if(source[i] < 32) {
strcpy(symbol->errtxt, "Control characters are not supported by GS1");
return ERROR_INVALID_DATA;
}
}
if(source[0] != '[') {
strcpy(symbol->errtxt, "Data does not start with an AI");
return ERROR_INVALID_DATA;
}
/* Check the position of the brackets */
bracket_level = 0;
max_bracket_level = 0;
ai_length = 0;
max_ai_length = 0;
min_ai_length = 5;
j = 0;
ai_latch = 0;
for(i = 0; i < src_len; i++) {
ai_length += j;
if(((j == 1) && (source[i] != ']')) && ((source[i] < '0') || (source[i] > '9'))) { ai_latch = 1; }
if(source[i] == '[') { bracket_level++; j = 1; }
if(source[i] == ']') {
bracket_level--;
if(ai_length < min_ai_length) { min_ai_length = ai_length; }
j = 0;
ai_length = 0;
}
if(bracket_level > max_bracket_level) { max_bracket_level = bracket_level; }
if(ai_length > max_ai_length) { max_ai_length = ai_length; }
}
min_ai_length--;
if(bracket_level != 0) {
/* Not all brackets are closed */
strcpy(symbol->errtxt, "Malformed AI in input data (brackets don\'t match)");
return ERROR_INVALID_DATA;
}
if(max_bracket_level > 1) {
/* Nested brackets */
strcpy(symbol->errtxt, "Found nested brackets in input data");
return ERROR_INVALID_DATA;
}
if(max_ai_length > 4) {
/* AI is too long */
strcpy(symbol->errtxt, "Invalid AI in input data (AI too long)");
return ERROR_INVALID_DATA;
}
if(min_ai_length <= 1) {
/* AI is too short */
strcpy(symbol->errtxt, "Invalid AI in input data (AI too short)");
return ERROR_INVALID_DATA;
}
if(ai_latch == 1) {
/* Non-numeric data in AI */
strcpy(symbol->errtxt, "Invalid AI in input data (non-numeric characters in AI)");
return ERROR_INVALID_DATA;
}
ai_count = 0;
for(i = 1; i < src_len; i++) {
if(source[i - 1] == '[') {
ai_location[ai_count] = i;
j = 0;
do {
ai_string[j] = source[i + j];
j++;
} while (ai_string[j - 1] != ']');
ai_string[j - 1] = '\0';
ai_value[ai_count] = atoi(ai_string);
ai_count++;
}
}
for(i = 0; i < ai_count; i++) {
data_location[i] = ai_location[i] + 3;
if(ai_value[i] >= 100) { data_location[i]++; }
if(ai_value[i] >= 1000) { data_location[i]++; }
data_length[i] = 0;
do {
data_length[i]++;
} while ((source[data_location[i] + data_length[i] - 1] != '[') && (source[data_location[i] + data_length[i] - 1] != '\0'));
data_length[i]--;
}
for(i = 0; i < ai_count; i++) {
if(data_length[i] == 0) {
/* No data for given AI */
strcpy(symbol->errtxt, "Empty data field in input data");
return ERROR_INVALID_DATA;
}
}
error_latch = 0;
strcpy(ai_string, "");
for(i = 0; i < ai_count; i++) {
switch (ai_value[i]) {
case 0: if(data_length[i] != 18) { error_latch = 1; } break;
case 1: if(data_length[i] != 14) { error_latch = 1; } break;
case 2: if(data_length[i] != 14) { error_latch = 1; } break;
case 3: if(data_length[i] != 14) { error_latch = 1; } break;
case 4: if(data_length[i] != 16) { error_latch = 1; } break;
case 11: if(data_length[i] != 6) { error_latch = 1; } break;
case 12: if(data_length[i] != 6) { error_latch = 1; } break;
case 13: if(data_length[i] != 6) { error_latch = 1; } break;
case 14: if(data_length[i] != 6) { error_latch = 1; } break;
case 15: if(data_length[i] != 6) { error_latch = 1; } break;
case 16: if(data_length[i] != 6) { error_latch = 1; } break;
case 17: if(data_length[i] != 6) { error_latch = 1; } break;
case 18: if(data_length[i] != 6) { error_latch = 1; } break;
case 19: if(data_length[i] != 6) { error_latch = 1; } break;
case 20: if(data_length[i] != 2) { error_latch = 1; } break;
case 23: error_latch = 2; break;
case 24: error_latch = 2; break;
case 25: error_latch = 2; break;
case 39: error_latch = 2; break;
case 40: error_latch = 2; break;
case 41: error_latch = 2; break;
case 42: error_latch = 2; break;
case 70: error_latch = 2; break;
case 80: error_latch = 2; break;
case 81: error_latch = 2; break;
}
if((ai_value[i] >= 100) && (ai_value[i] <= 179)) { error_latch = 2; }
if((ai_value[i] >= 1000) && (ai_value[i] <= 1799)) { error_latch = 2; }
if((ai_value[i] >= 200) && (ai_value[i] <= 229)) { error_latch = 2; }
if((ai_value[i] >= 2000) && (ai_value[i] <= 2299)) { error_latch = 2; }
if((ai_value[i] >= 300) && (ai_value[i] <= 309)) { error_latch = 2; }
if((ai_value[i] >= 3000) && (ai_value[i] <= 3099)) { error_latch = 2; }
if((ai_value[i] >= 31) && (ai_value[i] <= 36)) { error_latch = 2; }
if((ai_value[i] >= 310) && (ai_value[i] <= 369)) { error_latch = 2; }
if((ai_value[i] >= 3100) && (ai_value[i] <= 3699)) { if(data_length[i] != 6) { error_latch = 1; } }
if((ai_value[i] >= 370) && (ai_value[i] <= 379)) { error_latch = 2; }
if((ai_value[i] >= 3700) && (ai_value[i] <= 3799)) { error_latch = 2; }
if((ai_value[i] >= 410) && (ai_value[i] <= 415)) { if(data_length[i] != 13) { error_latch = 1; } }
if((ai_value[i] >= 4100) && (ai_value[i] <= 4199)) { error_latch = 2; }
if((ai_value[i] >= 700) && (ai_value[i] <= 703)) { error_latch = 2; }
if((ai_value[i] >= 800) && (ai_value[i] <= 810)) { error_latch = 2; }
if((ai_value[i] >= 900) && (ai_value[i] <= 999)) { error_latch = 2; }
if((ai_value[i] >= 9000) && (ai_value[i] <= 9999)) { error_latch = 2; }
if((error_latch < 4) && (error_latch > 0)) {
/* error has just been detected: capture AI */
itostr(ai_string, ai_value[i]);
error_latch += 4;
}
}
if(error_latch == 5) {
strcpy(symbol->errtxt, "Invalid data length for AI ");
concat(symbol->errtxt, ai_string);
return ERROR_INVALID_DATA;
}
if(error_latch == 6) {
strcpy(symbol->errtxt, "Invalid AI value ");
concat(symbol->errtxt, ai_string);
return ERROR_INVALID_DATA;
}
/* Resolve AI data - put resulting string in 'reduced' */
j = 0;
last_ai = 0;
ai_latch = 1;
for(i = 0; i < src_len; i++) {
if((source[i] != '[') && (source[i] != ']')) {
reduced[j++] = source[i];
}
if(source[i] == '[') {
/* Start of an AI string */
if(ai_latch == 0) {
reduced[j++] = '[';
}
ai_string[0] = source[i + 1];
ai_string[1] = source[i + 2];
ai_string[2] = '\0';
last_ai = atoi(ai_string);
ai_latch = 0;
/* The following values from "GS-1 General Specification version 8.0 issue 2, May 2008"
figure 5.4.8.2.1 - 1 "Element Strings with Pre-Defined Length Using Application Identifiers" */
if((last_ai >= 0) && (last_ai <= 4)) { ai_latch = 1; }
if((last_ai >= 11) && (last_ai <= 20)) { ai_latch = 1; }
if(last_ai == 23) { ai_latch = 1; } /* legacy support - see 5.3.8.2.2 */
if((last_ai >= 31) && (last_ai <= 36)) { ai_latch = 1; }
if(last_ai == 41) { ai_latch = 1; }
}
/* The ']' character is simply dropped from the input */
}
reduced[j] = '\0';
/* the character '[' in the reduced string refers to the FNC1 character */
return 0;
}
int ugs1_verify(struct zint_symbol *symbol, unsigned char source[], const unsigned int src_len, unsigned char reduced[])
{
/* Only to keep the compiler happy */
#ifndef _MSC_VER
char temp[src_len + 5];
#else
char* temp = (char*)_alloca(src_len + 5);
#endif
int error_number;
error_number = gs1_verify(symbol, source, src_len, temp);
if(error_number != 0) { return error_number; }
if (strlen(temp) < src_len + 5) {
ustrcpy(reduced, (unsigned char*)temp);
return 0;
}
strcpy(symbol->errtxt, "ugs1_verify overflow");
return ERROR_INVALID_DATA;
}

35
backend/gs1.h Normal file
View file

@ -0,0 +1,35 @@
/* gs1.h - Verifies GS1 data */
/*
libzint - the open source barcode library
Copyright (C) 2009 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __GS1_H
#define __GS1_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
extern int gs1_verify(struct zint_symbol *symbol, unsigned char source[], const unsigned int src_len, char reduced[]);
extern int ugs1_verify(struct zint_symbol *symbol, unsigned char source[], const unsigned int src_len, unsigned char reduced[]);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GS1_H */

700
backend/imail.c Normal file
View file

@ -0,0 +1,700 @@
/* imail.c - Handles Intelligent Mail (aka OneCode) for USPS */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* The function "USPS_MSB_Math_CRC11GenerateFrameCheckSequence"
is Copyright (C) 2006 United States Postal Service */
static short int BCD[40] = {
0, 0, 0, 0,
1, 0, 0, 0,
0, 1, 0, 0,
1, 1, 0, 0,
0, 0, 1, 0,
1, 0, 1, 0,
0, 1, 1, 0,
1, 1, 1, 0,
0, 0, 0, 1,
1, 0, 0, 1
};
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "common.h"
#include "large.h"
#define SODIUM "0123456789-"
/* The following lookup tables were generated using the code in Appendix C */
static unsigned short AppxD_I[1287] = { /* Appendix D Table 1 - 5 of 13 characters */
0x001F, 0x1F00, 0x002F, 0x1E80, 0x0037, 0x1D80, 0x003B, 0x1B80, 0x003D, 0x1780,
0x003E, 0x0F80, 0x004F, 0x1E40, 0x0057, 0x1D40, 0x005B, 0x1B40, 0x005D, 0x1740,
0x005E, 0x0F40, 0x0067, 0x1CC0, 0x006B, 0x1AC0, 0x006D, 0x16C0, 0x006E, 0x0EC0,
0x0073, 0x19C0, 0x0075, 0x15C0, 0x0076, 0x0DC0, 0x0079, 0x13C0, 0x007A, 0x0BC0,
0x007C, 0x07C0, 0x008F, 0x1E20, 0x0097, 0x1D20, 0x009B, 0x1B20, 0x009D, 0x1720,
0x009E, 0x0F20, 0x00A7, 0x1CA0, 0x00AB, 0x1AA0, 0x00AD, 0x16A0, 0x00AE, 0x0EA0,
0x00B3, 0x19A0, 0x00B5, 0x15A0, 0x00B6, 0x0DA0, 0x00B9, 0x13A0, 0x00BA, 0x0BA0,
0x00BC, 0x07A0, 0x00C7, 0x1C60, 0x00CB, 0x1A60, 0x00CD, 0x1660, 0x00CE, 0x0E60,
0x00D3, 0x1960, 0x00D5, 0x1560, 0x00D6, 0x0D60, 0x00D9, 0x1360, 0x00DA, 0x0B60,
0x00DC, 0x0760, 0x00E3, 0x18E0, 0x00E5, 0x14E0, 0x00E6, 0x0CE0, 0x00E9, 0x12E0,
0x00EA, 0x0AE0, 0x00EC, 0x06E0, 0x00F1, 0x11E0, 0x00F2, 0x09E0, 0x00F4, 0x05E0,
0x00F8, 0x03E0, 0x010F, 0x1E10, 0x0117, 0x1D10, 0x011B, 0x1B10, 0x011D, 0x1710,
0x011E, 0x0F10, 0x0127, 0x1C90, 0x012B, 0x1A90, 0x012D, 0x1690, 0x012E, 0x0E90,
0x0133, 0x1990, 0x0135, 0x1590, 0x0136, 0x0D90, 0x0139, 0x1390, 0x013A, 0x0B90,
0x013C, 0x0790, 0x0147, 0x1C50, 0x014B, 0x1A50, 0x014D, 0x1650, 0x014E, 0x0E50,
0x0153, 0x1950, 0x0155, 0x1550, 0x0156, 0x0D50, 0x0159, 0x1350, 0x015A, 0x0B50,
0x015C, 0x0750, 0x0163, 0x18D0, 0x0165, 0x14D0, 0x0166, 0x0CD0, 0x0169, 0x12D0,
0x016A, 0x0AD0, 0x016C, 0x06D0, 0x0171, 0x11D0, 0x0172, 0x09D0, 0x0174, 0x05D0,
0x0178, 0x03D0, 0x0187, 0x1C30, 0x018B, 0x1A30, 0x018D, 0x1630, 0x018E, 0x0E30,
0x0193, 0x1930, 0x0195, 0x1530, 0x0196, 0x0D30, 0x0199, 0x1330, 0x019A, 0x0B30,
0x019C, 0x0730, 0x01A3, 0x18B0, 0x01A5, 0x14B0, 0x01A6, 0x0CB0, 0x01A9, 0x12B0,
0x01AA, 0x0AB0, 0x01AC, 0x06B0, 0x01B1, 0x11B0, 0x01B2, 0x09B0, 0x01B4, 0x05B0,
0x01B8, 0x03B0, 0x01C3, 0x1870, 0x01C5, 0x1470, 0x01C6, 0x0C70, 0x01C9, 0x1270,
0x01CA, 0x0A70, 0x01CC, 0x0670, 0x01D1, 0x1170, 0x01D2, 0x0970, 0x01D4, 0x0570,
0x01D8, 0x0370, 0x01E1, 0x10F0, 0x01E2, 0x08F0, 0x01E4, 0x04F0, 0x01E8, 0x02F0,
0x020F, 0x1E08, 0x0217, 0x1D08, 0x021B, 0x1B08, 0x021D, 0x1708, 0x021E, 0x0F08,
0x0227, 0x1C88, 0x022B, 0x1A88, 0x022D, 0x1688, 0x022E, 0x0E88, 0x0233, 0x1988,
0x0235, 0x1588, 0x0236, 0x0D88, 0x0239, 0x1388, 0x023A, 0x0B88, 0x023C, 0x0788,
0x0247, 0x1C48, 0x024B, 0x1A48, 0x024D, 0x1648, 0x024E, 0x0E48, 0x0253, 0x1948,
0x0255, 0x1548, 0x0256, 0x0D48, 0x0259, 0x1348, 0x025A, 0x0B48, 0x025C, 0x0748,
0x0263, 0x18C8, 0x0265, 0x14C8, 0x0266, 0x0CC8, 0x0269, 0x12C8, 0x026A, 0x0AC8,
0x026C, 0x06C8, 0x0271, 0x11C8, 0x0272, 0x09C8, 0x0274, 0x05C8, 0x0278, 0x03C8,
0x0287, 0x1C28, 0x028B, 0x1A28, 0x028D, 0x1628, 0x028E, 0x0E28, 0x0293, 0x1928,
0x0295, 0x1528, 0x0296, 0x0D28, 0x0299, 0x1328, 0x029A, 0x0B28, 0x029C, 0x0728,
0x02A3, 0x18A8, 0x02A5, 0x14A8, 0x02A6, 0x0CA8, 0x02A9, 0x12A8, 0x02AA, 0x0AA8,
0x02AC, 0x06A8, 0x02B1, 0x11A8, 0x02B2, 0x09A8, 0x02B4, 0x05A8, 0x02B8, 0x03A8,
0x02C3, 0x1868, 0x02C5, 0x1468, 0x02C6, 0x0C68, 0x02C9, 0x1268, 0x02CA, 0x0A68,
0x02CC, 0x0668, 0x02D1, 0x1168, 0x02D2, 0x0968, 0x02D4, 0x0568, 0x02D8, 0x0368,
0x02E1, 0x10E8, 0x02E2, 0x08E8, 0x02E4, 0x04E8, 0x0307, 0x1C18, 0x030B, 0x1A18,
0x030D, 0x1618, 0x030E, 0x0E18, 0x0313, 0x1918, 0x0315, 0x1518, 0x0316, 0x0D18,
0x0319, 0x1318, 0x031A, 0x0B18, 0x031C, 0x0718, 0x0323, 0x1898, 0x0325, 0x1498,
0x0326, 0x0C98, 0x0329, 0x1298, 0x032A, 0x0A98, 0x032C, 0x0698, 0x0331, 0x1198,
0x0332, 0x0998, 0x0334, 0x0598, 0x0338, 0x0398, 0x0343, 0x1858, 0x0345, 0x1458,
0x0346, 0x0C58, 0x0349, 0x1258, 0x034A, 0x0A58, 0x034C, 0x0658, 0x0351, 0x1158,
0x0352, 0x0958, 0x0354, 0x0558, 0x0361, 0x10D8, 0x0362, 0x08D8, 0x0364, 0x04D8,
0x0383, 0x1838, 0x0385, 0x1438, 0x0386, 0x0C38, 0x0389, 0x1238, 0x038A, 0x0A38,
0x038C, 0x0638, 0x0391, 0x1138, 0x0392, 0x0938, 0x0394, 0x0538, 0x03A1, 0x10B8,
0x03A2, 0x08B8, 0x03A4, 0x04B8, 0x03C1, 0x1078, 0x03C2, 0x0878, 0x03C4, 0x0478,
0x040F, 0x1E04, 0x0417, 0x1D04, 0x041B, 0x1B04, 0x041D, 0x1704, 0x041E, 0x0F04,
0x0427, 0x1C84, 0x042B, 0x1A84, 0x042D, 0x1684, 0x042E, 0x0E84, 0x0433, 0x1984,
0x0435, 0x1584, 0x0436, 0x0D84, 0x0439, 0x1384, 0x043A, 0x0B84, 0x043C, 0x0784,
0x0447, 0x1C44, 0x044B, 0x1A44, 0x044D, 0x1644, 0x044E, 0x0E44, 0x0453, 0x1944,
0x0455, 0x1544, 0x0456, 0x0D44, 0x0459, 0x1344, 0x045A, 0x0B44, 0x045C, 0x0744,
0x0463, 0x18C4, 0x0465, 0x14C4, 0x0466, 0x0CC4, 0x0469, 0x12C4, 0x046A, 0x0AC4,
0x046C, 0x06C4, 0x0471, 0x11C4, 0x0472, 0x09C4, 0x0474, 0x05C4, 0x0487, 0x1C24,
0x048B, 0x1A24, 0x048D, 0x1624, 0x048E, 0x0E24, 0x0493, 0x1924, 0x0495, 0x1524,
0x0496, 0x0D24, 0x0499, 0x1324, 0x049A, 0x0B24, 0x049C, 0x0724, 0x04A3, 0x18A4,
0x04A5, 0x14A4, 0x04A6, 0x0CA4, 0x04A9, 0x12A4, 0x04AA, 0x0AA4, 0x04AC, 0x06A4,
0x04B1, 0x11A4, 0x04B2, 0x09A4, 0x04B4, 0x05A4, 0x04C3, 0x1864, 0x04C5, 0x1464,
0x04C6, 0x0C64, 0x04C9, 0x1264, 0x04CA, 0x0A64, 0x04CC, 0x0664, 0x04D1, 0x1164,
0x04D2, 0x0964, 0x04D4, 0x0564, 0x04E1, 0x10E4, 0x04E2, 0x08E4, 0x0507, 0x1C14,
0x050B, 0x1A14, 0x050D, 0x1614, 0x050E, 0x0E14, 0x0513, 0x1914, 0x0515, 0x1514,
0x0516, 0x0D14, 0x0519, 0x1314, 0x051A, 0x0B14, 0x051C, 0x0714, 0x0523, 0x1894,
0x0525, 0x1494, 0x0526, 0x0C94, 0x0529, 0x1294, 0x052A, 0x0A94, 0x052C, 0x0694,
0x0531, 0x1194, 0x0532, 0x0994, 0x0534, 0x0594, 0x0543, 0x1854, 0x0545, 0x1454,
0x0546, 0x0C54, 0x0549, 0x1254, 0x054A, 0x0A54, 0x054C, 0x0654, 0x0551, 0x1154,
0x0552, 0x0954, 0x0561, 0x10D4, 0x0562, 0x08D4, 0x0583, 0x1834, 0x0585, 0x1434,
0x0586, 0x0C34, 0x0589, 0x1234, 0x058A, 0x0A34, 0x058C, 0x0634, 0x0591, 0x1134,
0x0592, 0x0934, 0x05A1, 0x10B4, 0x05A2, 0x08B4, 0x05C1, 0x1074, 0x05C2, 0x0874,
0x0607, 0x1C0C, 0x060B, 0x1A0C, 0x060D, 0x160C, 0x060E, 0x0E0C, 0x0613, 0x190C,
0x0615, 0x150C, 0x0616, 0x0D0C, 0x0619, 0x130C, 0x061A, 0x0B0C, 0x061C, 0x070C,
0x0623, 0x188C, 0x0625, 0x148C, 0x0626, 0x0C8C, 0x0629, 0x128C, 0x062A, 0x0A8C,
0x062C, 0x068C, 0x0631, 0x118C, 0x0632, 0x098C, 0x0643, 0x184C, 0x0645, 0x144C,
0x0646, 0x0C4C, 0x0649, 0x124C, 0x064A, 0x0A4C, 0x0651, 0x114C, 0x0652, 0x094C,
0x0661, 0x10CC, 0x0662, 0x08CC, 0x0683, 0x182C, 0x0685, 0x142C, 0x0686, 0x0C2C,
0x0689, 0x122C, 0x068A, 0x0A2C, 0x0691, 0x112C, 0x0692, 0x092C, 0x06A1, 0x10AC,
0x06A2, 0x08AC, 0x06C1, 0x106C, 0x06C2, 0x086C, 0x0703, 0x181C, 0x0705, 0x141C,
0x0706, 0x0C1C, 0x0709, 0x121C, 0x070A, 0x0A1C, 0x0711, 0x111C, 0x0712, 0x091C,
0x0721, 0x109C, 0x0722, 0x089C, 0x0741, 0x105C, 0x0742, 0x085C, 0x0781, 0x103C,
0x0782, 0x083C, 0x080F, 0x1E02, 0x0817, 0x1D02, 0x081B, 0x1B02, 0x081D, 0x1702,
0x081E, 0x0F02, 0x0827, 0x1C82, 0x082B, 0x1A82, 0x082D, 0x1682, 0x082E, 0x0E82,
0x0833, 0x1982, 0x0835, 0x1582, 0x0836, 0x0D82, 0x0839, 0x1382, 0x083A, 0x0B82,
0x0847, 0x1C42, 0x084B, 0x1A42, 0x084D, 0x1642, 0x084E, 0x0E42, 0x0853, 0x1942,
0x0855, 0x1542, 0x0856, 0x0D42, 0x0859, 0x1342, 0x085A, 0x0B42, 0x0863, 0x18C2,
0x0865, 0x14C2, 0x0866, 0x0CC2, 0x0869, 0x12C2, 0x086A, 0x0AC2, 0x0871, 0x11C2,
0x0872, 0x09C2, 0x0887, 0x1C22, 0x088B, 0x1A22, 0x088D, 0x1622, 0x088E, 0x0E22,
0x0893, 0x1922, 0x0895, 0x1522, 0x0896, 0x0D22, 0x0899, 0x1322, 0x089A, 0x0B22,
0x08A3, 0x18A2, 0x08A5, 0x14A2, 0x08A6, 0x0CA2, 0x08A9, 0x12A2, 0x08AA, 0x0AA2,
0x08B1, 0x11A2, 0x08B2, 0x09A2, 0x08C3, 0x1862, 0x08C5, 0x1462, 0x08C6, 0x0C62,
0x08C9, 0x1262, 0x08CA, 0x0A62, 0x08D1, 0x1162, 0x08D2, 0x0962, 0x08E1, 0x10E2,
0x0907, 0x1C12, 0x090B, 0x1A12, 0x090D, 0x1612, 0x090E, 0x0E12, 0x0913, 0x1912,
0x0915, 0x1512, 0x0916, 0x0D12, 0x0919, 0x1312, 0x091A, 0x0B12, 0x0923, 0x1892,
0x0925, 0x1492, 0x0926, 0x0C92, 0x0929, 0x1292, 0x092A, 0x0A92, 0x0931, 0x1192,
0x0932, 0x0992, 0x0943, 0x1852, 0x0945, 0x1452, 0x0946, 0x0C52, 0x0949, 0x1252,
0x094A, 0x0A52, 0x0951, 0x1152, 0x0961, 0x10D2, 0x0983, 0x1832, 0x0985, 0x1432,
0x0986, 0x0C32, 0x0989, 0x1232, 0x098A, 0x0A32, 0x0991, 0x1132, 0x09A1, 0x10B2,
0x09C1, 0x1072, 0x0A07, 0x1C0A, 0x0A0B, 0x1A0A, 0x0A0D, 0x160A, 0x0A0E, 0x0E0A,
0x0A13, 0x190A, 0x0A15, 0x150A, 0x0A16, 0x0D0A, 0x0A19, 0x130A, 0x0A1A, 0x0B0A,
0x0A23, 0x188A, 0x0A25, 0x148A, 0x0A26, 0x0C8A, 0x0A29, 0x128A, 0x0A2A, 0x0A8A,
0x0A31, 0x118A, 0x0A43, 0x184A, 0x0A45, 0x144A, 0x0A46, 0x0C4A, 0x0A49, 0x124A,
0x0A51, 0x114A, 0x0A61, 0x10CA, 0x0A83, 0x182A, 0x0A85, 0x142A, 0x0A86, 0x0C2A,
0x0A89, 0x122A, 0x0A91, 0x112A, 0x0AA1, 0x10AA, 0x0AC1, 0x106A, 0x0B03, 0x181A,
0x0B05, 0x141A, 0x0B06, 0x0C1A, 0x0B09, 0x121A, 0x0B11, 0x111A, 0x0B21, 0x109A,
0x0B41, 0x105A, 0x0B81, 0x103A, 0x0C07, 0x1C06, 0x0C0B, 0x1A06, 0x0C0D, 0x1606,
0x0C0E, 0x0E06, 0x0C13, 0x1906, 0x0C15, 0x1506, 0x0C16, 0x0D06, 0x0C19, 0x1306,
0x0C23, 0x1886, 0x0C25, 0x1486, 0x0C26, 0x0C86, 0x0C29, 0x1286, 0x0C31, 0x1186,
0x0C43, 0x1846, 0x0C45, 0x1446, 0x0C49, 0x1246, 0x0C51, 0x1146, 0x0C61, 0x10C6,
0x0C83, 0x1826, 0x0C85, 0x1426, 0x0C89, 0x1226, 0x0C91, 0x1126, 0x0CA1, 0x10A6,
0x0CC1, 0x1066, 0x0D03, 0x1816, 0x0D05, 0x1416, 0x0D09, 0x1216, 0x0D11, 0x1116,
0x0D21, 0x1096, 0x0D41, 0x1056, 0x0D81, 0x1036, 0x0E03, 0x180E, 0x0E05, 0x140E,
0x0E09, 0x120E, 0x0E11, 0x110E, 0x0E21, 0x108E, 0x0E41, 0x104E, 0x0E81, 0x102E,
0x0F01, 0x101E, 0x100F, 0x1E01, 0x1017, 0x1D01, 0x101B, 0x1B01, 0x101D, 0x1701,
0x1027, 0x1C81, 0x102B, 0x1A81, 0x102D, 0x1681, 0x1033, 0x1981, 0x1035, 0x1581,
0x1039, 0x1381, 0x1047, 0x1C41, 0x104B, 0x1A41, 0x104D, 0x1641, 0x1053, 0x1941,
0x1055, 0x1541, 0x1059, 0x1341, 0x1063, 0x18C1, 0x1065, 0x14C1, 0x1069, 0x12C1,
0x1071, 0x11C1, 0x1087, 0x1C21, 0x108B, 0x1A21, 0x108D, 0x1621, 0x1093, 0x1921,
0x1095, 0x1521, 0x1099, 0x1321, 0x10A3, 0x18A1, 0x10A5, 0x14A1, 0x10A9, 0x12A1,
0x10B1, 0x11A1, 0x10C3, 0x1861, 0x10C5, 0x1461, 0x10C9, 0x1261, 0x10D1, 0x1161,
0x1107, 0x1C11, 0x110B, 0x1A11, 0x110D, 0x1611, 0x1113, 0x1911, 0x1115, 0x1511,
0x1119, 0x1311, 0x1123, 0x1891, 0x1125, 0x1491, 0x1129, 0x1291, 0x1131, 0x1191,
0x1143, 0x1851, 0x1145, 0x1451, 0x1149, 0x1251, 0x1183, 0x1831, 0x1185, 0x1431,
0x1189, 0x1231, 0x1207, 0x1C09, 0x120B, 0x1A09, 0x120D, 0x1609, 0x1213, 0x1909,
0x1215, 0x1509, 0x1219, 0x1309, 0x1223, 0x1889, 0x1225, 0x1489, 0x1229, 0x1289,
0x1243, 0x1849, 0x1245, 0x1449, 0x1283, 0x1829, 0x1285, 0x1429, 0x1303, 0x1819,
0x1305, 0x1419, 0x1407, 0x1C05, 0x140B, 0x1A05, 0x140D, 0x1605, 0x1413, 0x1905,
0x1415, 0x1505, 0x1423, 0x1885, 0x1425, 0x1485, 0x1443, 0x1845, 0x1483, 0x1825,
0x1503, 0x1815, 0x1603, 0x180D, 0x1807, 0x1C03, 0x180B, 0x1A03, 0x1813, 0x1903,
0x1823, 0x1883, 0x1843, 0x1445, 0x1249, 0x1151, 0x10E1, 0x0C46, 0x0A4A, 0x0952,
0x08E2, 0x064C, 0x0554, 0x04E4, 0x0358, 0x02E8, 0x01F0 };
static unsigned short AppxD_II[78] = { /* Appendix D Table II - 2 of 13 characters */
0x0003, 0x1800, 0x0005, 0x1400, 0x0006, 0x0C00, 0x0009, 0x1200, 0x000A, 0x0A00,
0x000C, 0x0600, 0x0011, 0x1100, 0x0012, 0x0900, 0x0014, 0x0500, 0x0018, 0x0300,
0x0021, 0x1080, 0x0022, 0x0880, 0x0024, 0x0480, 0x0028, 0x0280, 0x0030, 0x0180,
0x0041, 0x1040, 0x0042, 0x0840, 0x0044, 0x0440, 0x0048, 0x0240, 0x0050, 0x0140,
0x0060, 0x00C0, 0x0081, 0x1020, 0x0082, 0x0820, 0x0084, 0x0420, 0x0088, 0x0220,
0x0090, 0x0120, 0x0101, 0x1010, 0x0102, 0x0810, 0x0104, 0x0410, 0x0108, 0x0210,
0x0201, 0x1008, 0x0202, 0x0808, 0x0204, 0x0408, 0x0401, 0x1004, 0x0402, 0x0804,
0x0801, 0x1002, 0x1001, 0x0802, 0x0404, 0x0208, 0x0110, 0x00A0 };
static int AppxD_IV[130] = { /* Appendix D Table IV - Bar-to-Character Mapping (reverse lookup) */
67, 6, 78, 16, 86, 95, 34, 40, 45, 113, 117, 121, 62, 87, 18, 104, 41, 76, 57, 119, 115, 72, 97,
2, 127, 26, 105, 35, 122, 52, 114, 7, 24, 82, 68, 63, 94, 44, 77, 112, 70, 100, 39, 30, 107,
15, 125, 85, 10, 65, 54, 88, 20, 106, 46, 66, 8, 116, 29, 61, 99, 80, 90, 37, 123, 51, 25, 84,
129, 56, 4, 109, 96, 28, 36, 47, 11, 71, 33, 102, 21, 9, 17, 49, 124, 79, 64, 91, 42, 69, 53,
60, 14, 1, 27, 103, 126, 75, 89, 50, 120, 19, 32, 110, 92, 111, 130, 59, 31, 12, 81, 43, 55,
5, 74, 22, 101, 128, 58, 118, 48, 108, 38, 98, 93, 23, 83, 13, 73, 3 };
/***************************************************************************
** USPS_MSB_Math_CRC11GenerateFrameCheckSequence
**
** Inputs:
** ByteAttayPtr is the address of a 13 byte array holding 102 bytes which
** are right justified - ie: the leftmost 2 bits of the first byte do not
** hold data and must be set to zero.
**
** Outputs:
** return unsigned short - 11 bit Frame Check Sequence (right justified)
***************************************************************************/
extern unsigned short
USPS_MSB_Math_CRC11GenerateFrameCheckSequence( unsigned char *ByteArrayPtr )
{
unsigned short GeneratorPolynomial = 0x0F35;
unsigned short FrameCheckSequence = 0x07FF;
unsigned short Data;
int ByteIndex, Bit;
/* Do most significant byte skipping the 2 most significant bits */
Data = *ByteArrayPtr << 5;
ByteArrayPtr++;
for ( Bit = 2; Bit < 8; Bit++ )
{
if ( (FrameCheckSequence ^ Data) & 0x400 )
FrameCheckSequence = (FrameCheckSequence << 1) ^ GeneratorPolynomial;
else
FrameCheckSequence = (FrameCheckSequence << 1);
FrameCheckSequence &= 0x7FF;
Data <<= 1;
}
/* Do rest of the bytes */
for ( ByteIndex = 1; ByteIndex < 13; ByteIndex++ )
{
Data = *ByteArrayPtr << 3;
ByteArrayPtr++;
for ( Bit = 0; Bit < 8; Bit++ )
{
if ( (FrameCheckSequence ^ Data) & 0x0400 ) {
FrameCheckSequence = (FrameCheckSequence << 1) ^ GeneratorPolynomial;
} else {
FrameCheckSequence = (FrameCheckSequence << 1);
}
FrameCheckSequence &= 0x7FF;
Data <<= 1;
}
}
return FrameCheckSequence;
}
void breakup(short int fcs_bit[], unsigned short usps_crc)
{
int i;
for(i = 0; i < 13; i++) {
fcs_bit[i] = 0;
}
if(usps_crc >= 4096) {
fcs_bit[12] = 1;
usps_crc -= 4096;
}
if(usps_crc >= 2048) {
fcs_bit[11] = 1;
usps_crc -= 2048;
}
if(usps_crc >= 1024) {
fcs_bit[10] = 1;
usps_crc -= 1024;
}
if(usps_crc >= 512) {
fcs_bit[9] = 1;
usps_crc -= 512;
}
if(usps_crc >= 256) {
fcs_bit[8] = 1;
usps_crc -= 256;
}
if(usps_crc >= 128) {
fcs_bit[7] = 1;
usps_crc -= 128;
}
if(usps_crc >= 64) {
fcs_bit[6] = 1;
usps_crc -= 64;
}
if(usps_crc >= 32) {
fcs_bit[5] = 1;
usps_crc -= 32;
}
if(usps_crc >= 16) {
fcs_bit[4] = 1;
usps_crc -= 16;
}
if(usps_crc >= 8) {
fcs_bit[3] = 1;
usps_crc -= 8;
}
if(usps_crc >= 4) {
fcs_bit[2] = 1;
usps_crc -= 4;
}
if(usps_crc >= 2) {
fcs_bit[1] = 1;
usps_crc -= 2;
}
if(usps_crc == 1) {
fcs_bit[0] = 1;
}
}
int imail(struct zint_symbol *symbol, unsigned char source[], int length)
{
char data_pattern[200];
int error_number;
int i, j, read;
char zip[35], tracker[35], zip_adder[11], temp[2];
short int accum[112], x_reg[112], y_reg[112];
unsigned char byte_array[13];
unsigned short usps_crc;
int codeword[10];
unsigned short characters[10];
short int bit_pattern[13], bar_map[130];
error_number = 0;
if(length > 32) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(SODIUM, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
strcpy(zip, "");
strcpy(tracker, "");
/* separate the tracking code from the routing code */
read = 0;
j = 0;
for(i = 0; i < length; i++) {
if(source[i] == '-') {
tracker[read] = '\0';
j = 1;
read = 0;
} else {
if(j == 0) {
/* reading tracker */
tracker[read] = source[i];
read++;
} else {
/* reading zip code */
zip[read] = source[i];
read++;
}
}
}
if(j == 0) {
tracker[read] = '\0';
} else {
zip[read] = '\0';
}
if(strlen(tracker) != 20) {
strcpy(symbol->errtxt, "Invalid length tracking code");
return ERROR_INVALID_DATA;
}
if(strlen(zip) > 11) {
strcpy(symbol->errtxt, "Invalid ZIP code");
return ERROR_INVALID_DATA;
}
/* *** Step 1 - Conversion of Data Fields into Binary Data *** */
/* Routing code first */
for(i = 0; i < 112; i++) {
accum[i] = 0;
}
for(read = 0; read < strlen(zip); read++) {
for(i = 0; i < 112; i++) {
x_reg[i] = accum[i];
}
for(i = 0; i < 9; i++) {
binary_add(accum, x_reg);
}
x_reg[0] = BCD[ctoi(zip[read]) * 4];
x_reg[1] = BCD[(ctoi(zip[read]) * 4) + 1];
x_reg[2] = BCD[(ctoi(zip[read]) * 4) + 2];
x_reg[3] = BCD[(ctoi(zip[read]) * 4) + 3];
for(i = 4; i < 112; i++) {
x_reg[i] = 0;
}
binary_add(accum, x_reg);
}
/* add weight to routing code */
for(i = 0; i < 112; i++) {
x_reg[i] = accum[i];
}
if(strlen(zip) > 9) {
strcpy(zip_adder, "1000100001");
} else {
if(strlen(zip) > 5) {
strcpy(zip_adder, "100001");
} else {
if(strlen(zip) > 0) {
strcpy(zip_adder, "1");
} else {
strcpy(zip_adder, "0");
}
}
}
for(i = 0; i < 112; i++) {
accum[i] = 0;
}
for(read = 0; read < strlen(zip_adder); read++) {
for(i = 0; i < 112; i++) {
y_reg[i] = accum[i];
}
for(i = 0; i < 9; i++) {
binary_add(accum, y_reg);
}
y_reg[0] = BCD[ctoi(zip_adder[read]) * 4];
y_reg[1] = BCD[(ctoi(zip_adder[read]) * 4) + 1];
y_reg[2] = BCD[(ctoi(zip_adder[read]) * 4) + 2];
y_reg[3] = BCD[(ctoi(zip_adder[read]) * 4) + 3];
for(i = 4; i < 112; i++) {
y_reg[i] = 0;
}
binary_add(accum, y_reg);
}
binary_add(accum, x_reg);
/* tracking code */
/* multiply by 10 */
for(i = 0; i < 112; i++) {
y_reg[i] = accum[i];
}
for(i = 0; i < 9; i++) {
binary_add(accum, y_reg);
}
/* add first digit of tracker */
y_reg[0] = BCD[ctoi(tracker[0]) * 4];
y_reg[1] = BCD[(ctoi(tracker[0]) * 4) + 1];
y_reg[2] = BCD[(ctoi(tracker[0]) * 4) + 2];
y_reg[3] = BCD[(ctoi(tracker[0]) * 4) + 3];
for(i = 4; i < 112; i++) {
y_reg[i] = 0;
}
binary_add(accum, y_reg);
/* multiply by 5 */
for(i = 0; i < 112; i++) {
y_reg[i] = accum[i];
}
for(i = 0; i < 4; i++) {
binary_add(accum, y_reg);
}
/* add second digit */
y_reg[0] = BCD[ctoi(tracker[1]) * 4];
y_reg[1] = BCD[(ctoi(tracker[1]) * 4) + 1];
y_reg[2] = BCD[(ctoi(tracker[1]) * 4) + 2];
y_reg[3] = BCD[(ctoi(tracker[1]) * 4) + 3];
for(i = 4; i < 112; i++) {
y_reg[i] = 0;
}
binary_add(accum, y_reg);
/* and then the rest */
for(read = 2; read < strlen(tracker); read++) {
for(i = 0; i < 112; i++) {
y_reg[i] = accum[i];
}
for(i = 0; i < 9; i++) {
binary_add(accum, y_reg);
}
y_reg[0] = BCD[ctoi(tracker[read]) * 4];
y_reg[1] = BCD[(ctoi(tracker[read]) * 4) + 1];
y_reg[2] = BCD[(ctoi(tracker[read]) * 4) + 2];
y_reg[3] = BCD[(ctoi(tracker[read]) * 4) + 3];
for(i = 4; i < 112; i++) {
y_reg[i] = 0;
}
binary_add(accum, y_reg);
}
/* printf("Binary data 1: ");
hex_dump(accum); */
/* *** Step 2 - Generation of 11-bit CRC on Binary Data *** */
accum[103] = 0;
accum[102] = 0;
memset(byte_array, 0, 13);
for(j = 0; j < 13; j++) {
i = 96 - (8 * j);
byte_array[j] = 0;
byte_array[j] += accum[i];
byte_array[j] += 2 * accum[i + 1];
byte_array[j] += 4 * accum[i + 2];
byte_array[j] += 8 * accum[i + 3];
byte_array[j] += 16 * accum[i + 4];
byte_array[j] += 32 * accum[i + 5];
byte_array[j] += 64 * accum[i + 6];
byte_array[j] += 128 * accum[i + 7];
}
usps_crc = USPS_MSB_Math_CRC11GenerateFrameCheckSequence(byte_array);
/* printf("FCS 2: %4.4X\n", usps_crc); */
/* *** Step 3 - Conversion from Binary Data to Codewords *** */
/* start with codeword J which is base 636 */
for(i = 0; i < 112; i++) {
x_reg[i] = 0;
y_reg[i] = 0;
}
x_reg[101] = 1;
x_reg[98] = 1;
x_reg[97] = 1;
x_reg[96] = 1;
x_reg[95] = 1;
x_reg[94] = 1;
for(i = 92; i >= 0; i--) {
y_reg[i] = islarger(accum, x_reg);
if(y_reg[i] == 1) {
binary_subtract(accum, x_reg);
}
shiftdown(x_reg);
}
codeword[9] = (accum[9] * 512) + (accum[8] * 256) + (accum[7] * 128) + (accum[6] * 64) +
(accum[5] * 32) + (accum[4] * 16) + (accum[3] * 8) + (accum[2] * 4) +
(accum[1] * 2) + accum[0];
/* then codewords I to B with base 1365 */
for(j = 8; j > 0; j--) {
for(i = 0; i < 112; i++) {
accum[i] = y_reg[i];
y_reg[i] = 0;
x_reg[i] = 0;
}
x_reg[101] = 1;
x_reg[99] = 1;
x_reg[97] = 1;
x_reg[95] = 1;
x_reg[93] = 1;
x_reg[91] = 1;
for(i = 91; i >= 0; i--) {
y_reg[i] = islarger(accum, x_reg);
if(y_reg[i] == 1) {
binary_subtract(accum, x_reg);
}
shiftdown(x_reg);
}
codeword[j] = (accum[10] * 1024) + (accum[9] * 512) + (accum[8] * 256) +
(accum[7] * 128) + (accum[6] * 64) + (accum[5] * 32) +
(accum[4] * 16) + (accum[3] * 8) + (accum[2] * 4) +
(accum[1] * 2) + accum[0];
}
codeword[0] = (y_reg[10] * 1024) + (y_reg[9] * 512) + (y_reg[8] * 256) +
(y_reg[7] * 128) + (y_reg[6] * 64) + (y_reg[5] * 32) +
(y_reg[4] * 16) + (y_reg[3] * 8) + (y_reg[2] * 4) +
(y_reg[1] * 2) + y_reg[0];
for(i = 0; i < 8; i++) {
if(codeword[i] == 1365) {
codeword[i] = 0;
codeword[i + 1]++;
}
}
/* printf("Codewords 3: ");
for(i = 0; i < 10; i++) {
printf("%d ", codeword[i]);
}
printf("\n"); */
/* *** Step 4 - Inserting Additional Information into Codewords *** */
codeword[9] = codeword[9] * 2;
if(usps_crc >= 1024) {
codeword[0] += 659;
}
/* printf("Codewords 4b: ");
for(i = 0; i < 10; i++) {
printf("%d ", codeword[i]);
}
printf("\n"); */
/* *** Step 5 - Conversion from Codewords to Characters *** */
for(i = 0; i < 10; i++) {
if(codeword[i] < 1287) {
characters[i] = AppxD_I[codeword[i]];
} else {
characters[i] = AppxD_II[codeword[i] - 1287];
}
}
/* printf("Characters 5a: ");
for(i = 0; i < 10; i++) {
printf("%4.4X ", characters[i]);
}
printf("\n"); */
breakup(bit_pattern, usps_crc);
for(i = 0; i < 10; i++) {
if(bit_pattern[i] == 1) {
characters[i] = 0x1FFF - characters[i];
}
}
/* printf("Characters 5b: ");
for(i = 0; i < 10; i++) {
printf("%4.4X ", characters[i]);
}
printf("\n"); */
/* *** Step 6 - Conversion from Characters to the Intelligent Mail Barcode *** */
for(i = 0; i < 10; i++) {
breakup(bit_pattern, characters[i]);
for(j = 0; j < 13; j++) {
bar_map[AppxD_IV[(13 * i) + j] - 1] = bit_pattern[j];
}
}
strcpy(data_pattern, "");
temp[1] = '\0';
for(i = 0; i < 65; i++) {
j = 0;
if(bar_map[i] == 0)
j += 1;
if(bar_map[i + 65] == 0)
j += 2;
temp[0] = itoc(j);
concat(data_pattern, temp);
}
/* Translate 4-state data pattern to symbol */
read = 0;
for(i = 0; i < strlen(data_pattern); i++)
{
if((data_pattern[i] == '1') || (data_pattern[i] == '0'))
{
set_module(symbol, 0, read);
}
set_module(symbol, 1, read);
if((data_pattern[i] == '2') || (data_pattern[i] == '0'))
{
set_module(symbol, 2, read);
}
read += 2;
}
symbol->row_height[0] = 2;
symbol->row_height[1] = 2;
symbol->row_height[2] = 2;
symbol->rows = 3;
symbol->width = read - 1;
return error_number;
}

227
backend/large.c Normal file
View file

@ -0,0 +1,227 @@
/* large.c - Handles binary manipulation of large numbers */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <string.h>
#include "common.h"
#include "large.h"
static short int BCD[40] = {
0, 0, 0, 0,
1, 0, 0, 0,
0, 1, 0, 0,
1, 1, 0, 0,
0, 0, 1, 0,
1, 0, 1, 0,
0, 1, 1, 0,
1, 1, 1, 0,
0, 0, 0, 1,
1, 0, 0, 1 };
void binary_add(short int accumulator[], short int input_buffer[])
{ /* Binary addition */
int i, carry, done;
carry = 0;
for(i = 0; i < 112; i++) {
done = 0;
if(((input_buffer[i] == 0) && (accumulator[i] == 0)) && ((carry == 0) && (done == 0))) {
accumulator[i] = 0;
carry = 0;
done = 1;
}
if(((input_buffer[i] == 0) && (accumulator[i] == 0)) && ((carry == 1) && (done == 0))) {
accumulator[i] = 1;
carry = 0;
done = 1;
}
if(((input_buffer[i] == 0) && (accumulator[i] == 1)) && ((carry == 0) && (done == 0))) {
accumulator[i] = 1;
carry = 0;
done = 1;
}
if(((input_buffer[i] == 0) && (accumulator[i] == 1)) && ((carry == 1) && (done == 0))) {
accumulator[i] = 0;
carry = 1;
done = 1;
}
if(((input_buffer[i] == 1) && (accumulator[i] == 0)) && ((carry == 0) && (done == 0))) {
accumulator[i] = 1;
carry = 0;
done = 1;
}
if(((input_buffer[i] == 1) && (accumulator[i] == 0)) && ((carry == 1) && (done == 0))) {
accumulator[i] = 0;
carry = 1;
done = 1;
}
if(((input_buffer[i] == 1) && (accumulator[i] == 1)) && ((carry == 0) && (done == 0))) {
accumulator[i] = 0;
carry = 1;
done = 1;
}
if(((input_buffer[i] == 1) && (accumulator[i] == 1)) && ((carry == 1) && (done == 0))) {
accumulator[i] = 1;
carry = 1;
done = 1;
}
}
}
void binary_subtract(short int accumulator[], short int input_buffer[])
{ /* 2's compliment subtraction */
/* take input_buffer from accumulator and put answer in accumulator */
int i;
short int sub_buffer[112];
for(i = 0; i < 112; i++) {
if(input_buffer[i] == 0) {
sub_buffer[i] = 1;
} else {
sub_buffer[i] = 0;
}
}
binary_add(accumulator, sub_buffer);
sub_buffer[0] = 1;
for(i = 1; i < 112; i++) {
sub_buffer[i] = 0;
}
binary_add(accumulator, sub_buffer);
}
void shiftdown(short int buffer[])
{
int i;
buffer[102] = 0;
buffer[103] = 0;
for(i = 0; i < 102; i++) {
buffer[i] = buffer[i + 1];
}
}
void shiftup(short int buffer[])
{
int i;
for(i = 102; i > 0; i--) {
buffer[i] = buffer[i - 1];
}
buffer[0] = 0;
}
short int islarger(short int accum[], short int reg[])
{
/* Returns 1 if accum[] is larger than reg[], else 0 */
int i, latch, larger;
latch = 0;
i = 103;
larger = 0;
do {
if((accum[i] == 1) && (reg[i] == 0)) {
latch = 1;
larger = 1;
}
if((accum[i] == 0) && (reg[i] == 1)) {
latch = 1;
}
i--;
} while ((latch == 0) && (i >= -1));
return larger;
}
void binary_load(short int reg[], char data[], const unsigned int src_len)
{
int read, i;
short int temp[112] = { 0 };
for(i = 0; i < 112; i++) {
reg[i] = 0;
}
for(read = 0; read < src_len; read++) {
for(i = 0; i < 112; i++) {
temp[i] = reg[i];
}
for(i = 0; i < 9; i++) {
binary_add(reg, temp);
}
temp[0] = BCD[ctoi(data[read]) * 4];
temp[1] = BCD[(ctoi(data[read]) * 4) + 1];
temp[2] = BCD[(ctoi(data[read]) * 4) + 2];
temp[3] = BCD[(ctoi(data[read]) * 4) + 3];
for(i = 4; i < 112; i++) {
temp[i] = 0;
}
binary_add(reg, temp);
}
}
void hex_dump(short int input_buffer[])
{
int i, digit, byte_space;
byte_space = 1;
for(i = 100; i >= 0; i-=4) {
digit = 0;
digit += 1 * input_buffer[i];
digit += 2 * input_buffer[i + 1];
digit += 4 * input_buffer[i + 2];
digit += 8 * input_buffer[i + 3];
switch(digit) {
case 0: printf("0"); break;
case 1: printf("1"); break;
case 2: printf("2"); break;
case 3: printf("3"); break;
case 4: printf("4"); break;
case 5: printf("5"); break;
case 6: printf("6"); break;
case 7: printf("7"); break;
case 8: printf("8"); break;
case 9: printf("9"); break;
case 10: printf("A"); break;
case 11: printf("B"); break;
case 12: printf("C"); break;
case 13: printf("D"); break;
case 14: printf("E"); break;
case 15: printf("F"); break;
}
if(byte_space == 1) {
byte_space = 0;
} else {
byte_space = 1;
printf(" ");
}
}
printf("\n");
}

40
backend/large.h Normal file
View file

@ -0,0 +1,40 @@
/* large.h - Handles binary manipulation of large numbers */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __LARGE_H
#define __LARGE_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
extern void binary_load(short int reg[], char data[], const unsigned int src_len);
extern void binary_add(short int accumulator[], short int input_buffer[]);
extern void binary_subtract(short int accumulator[], short int input_buffer[]);
extern void shiftdown(short int buffer[]);
extern void shiftup(short int buffer[]);
extern short int islarger(short int accum[], short int reg[]);
extern void hex_dump(short int input_buffer[]);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __LARGE_H */

837
backend/library.c Normal file
View file

@ -0,0 +1,837 @@
/* library.c - external functions of libzint
libzint - the open source barcode library
Copyright (C) 2009 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifdef _MSC_VER
#include <malloc.h>
#endif
#include "common.h"
#include "gs1.h"
#define TECHNETIUM "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"
struct zint_symbol *ZBarcode_Create()
{
struct zint_symbol *symbol;
int i, j;
symbol = (struct zint_symbol*)malloc(sizeof(*symbol));
if (!symbol) return NULL;
memset(symbol, 0, sizeof(*symbol));
symbol->symbology = BARCODE_CODE128;
symbol->height = 0;
symbol->whitespace_width = 0;
symbol->border_width = 0;
symbol->output_options = 0;
symbol->rows = 0;
symbol->width = 0;
strcpy(symbol->fgcolour, "000000");
strcpy(symbol->bgcolour, "ffffff");
strcpy(symbol->outfile, "out.png");
symbol->scale = 1.0;
symbol->option_1 = -1;
symbol->option_2 = 0;
symbol->option_3 = 928; // PDF_MAX
symbol->show_hrt = 1; // Show human readable text
symbol->input_mode = DATA_MODE;
strcpy(symbol->primary, "");
for(i = 0; i < 178; i++) {
for(j = 0; j < 1000; j++) {
unset_module(symbol, i, j);
}
symbol->row_height[i] = 0;
}
symbol->bitmap = NULL;
symbol->bitmap_width = 0;
symbol->bitmap_height = 0;
return symbol;
}
void ZBarcode_Clear(struct zint_symbol *symbol)
{
int i, j;
for(i = 0; i < symbol->rows; i++) {
for(j = 0; j < symbol->width; j++) {
unset_module(symbol, i, j);
}
}
symbol->rows = 0;
symbol->width = 0;
symbol->text[0] = '\0';
symbol->errtxt[0] = '\0';
if (symbol->bitmap != NULL)
free(symbol->bitmap);
symbol->bitmap = NULL;
symbol->bitmap_width = 0;
symbol->bitmap_height = 0;
}
void ZBarcode_Delete(struct zint_symbol *symbol)
{
if (symbol->bitmap != NULL)
free(symbol->bitmap);
free(symbol);
}
extern int eanx(struct zint_symbol *symbol, unsigned char source[], int length); /* EAN system barcodes */
extern int c39(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 3 from 9 (or Code 39) */
extern int pharmazentral(struct zint_symbol *symbol, unsigned char source[], int length); /* Pharmazentral Nummer (PZN) */
extern int ec39(struct zint_symbol *symbol, unsigned char source[], int length); /* Extended Code 3 from 9 (or Code 39+) */
extern int codabar(struct zint_symbol *symbol, unsigned char source[], int length); /* Codabar - a simple substitution cipher */
extern int matrix_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Standard (& Matrix) */
extern int industrial_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Industrial */
extern int iata_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 IATA */
extern int interleaved_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Interleaved */
extern int logic_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Data Logic */
extern int itf14(struct zint_symbol *symbol, unsigned char source[], int length); /* ITF-14 */
extern int dpleit(struct zint_symbol *symbol, unsigned char source[], int length); /* Deutsche Post Leitcode */
extern int dpident(struct zint_symbol *symbol, unsigned char source[], int length); /* Deutsche Post Identcode */
extern int c93(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 93 - a re-working of Code 39+, generates 2 check digits */
extern int code_128(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 128 and NVE-18 */
extern int ean_128(struct zint_symbol *symbol, unsigned char source[], int length); /* EAN-128 (GS1-128) */
extern int code_11(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 11 */
extern int msi_handle(struct zint_symbol *symbol, unsigned char source[], int length); /* MSI Plessey */
extern int telepen(struct zint_symbol *symbol, unsigned char source[], int length); /* Telepen ASCII */
extern int telepen_num(struct zint_symbol *symbol, unsigned char source[], int length); /* Telepen Numeric */
extern int plessey(struct zint_symbol *symbol, unsigned char source[], int length); /* Plessey Code */
extern int pharma_one(struct zint_symbol *symbol, unsigned char source[], int length); /* Pharmacode One Track */
extern int flattermarken(struct zint_symbol *symbol, unsigned char source[], int length); /* Flattermarken */
extern int fim(struct zint_symbol *symbol, unsigned char source[], int length); /* Facing Identification Mark */
extern int pharma_two(struct zint_symbol *symbol, unsigned char source[], int length); /* Pharmacode Two Track */
extern int post_plot(struct zint_symbol *symbol, unsigned char source[], int length); /* Postnet */
extern int planet_plot(struct zint_symbol *symbol, unsigned char source[], int length); /* PLANET */
extern int imail(struct zint_symbol *symbol, unsigned char source[], int length); /* Intelligent Mail (aka USPS OneCode) */
extern int royal_plot(struct zint_symbol *symbol, unsigned char source[], int length); /* RM4SCC */
extern int australia_post(struct zint_symbol *symbol, unsigned char source[], int length); /* Australia Post 4-state */
extern int code16k(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 16k */
extern int pdf417enc(struct zint_symbol *symbol, unsigned char source[], int length); /* PDF417 */
extern int dmatrix(struct zint_symbol *symbol, unsigned char source[], int length); /* Data Matrix (IEC16022) */
extern int qr_code(struct zint_symbol *symbol, unsigned char source[], int length); /* QR Code */
extern int micro_pdf417(struct zint_symbol *symbol, unsigned char chaine[], int length); /* Micro PDF417 */
extern int maxicode(struct zint_symbol *symbol, unsigned char source[], int length); /* Maxicode */
extern int rss14(struct zint_symbol *symbol, unsigned char source[], int length); /* RSS-14 */
extern int rsslimited(struct zint_symbol *symbol, unsigned char source[], int length); /* RSS Limited */
extern int rssexpanded(struct zint_symbol *symbol, unsigned char source[], int length); /* RSS Expanded */
extern int composite(struct zint_symbol *symbol, unsigned char source[], int length); /* Composite Symbology */
extern int kix_code(struct zint_symbol *symbol, unsigned char source[], int length); /* TNT KIX Code */
extern int aztec(struct zint_symbol *symbol, unsigned char source[], int length); /* Aztec Code */
extern int code32(struct zint_symbol *symbol, unsigned char source[], int length); /* Italian Pharmacode */
extern int daft_code(struct zint_symbol *symbol, unsigned char source[], int length); /* DAFT Code */
extern int ean_14(struct zint_symbol *symbol, unsigned char source[], int length); /* EAN-14 */
extern int nve_18(struct zint_symbol *symbol, unsigned char source[], int length); /* NVE-18 */
extern int microqr(struct zint_symbol *symbol, unsigned char source[], int length); /* Micro QR Code */
extern int aztec_runes(struct zint_symbol *symbol, unsigned char source[], int length); /* Aztec Runes */
extern int korea_post(struct zint_symbol *symbol, unsigned char source[], int length); /* Korea Post */
extern int japan_post(struct zint_symbol *symbol, unsigned char source[], int length); /* Japanese Post */
extern int code_49(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 49 */
extern int channel_code(struct zint_symbol *symbol, unsigned char source[], int length); /* Channel Code */
extern int code_one(struct zint_symbol *symbol, unsigned char source[], int length); /* Code One */
extern int grid_matrix(struct zint_symbol *symbol, unsigned char source[], int length); /* Grid Matrix */
#ifndef NO_PNG
extern int png_handle(struct zint_symbol *symbol, int rotate_angle);
#endif
extern int bmp_handle(struct zint_symbol *symbol, int rotate_angle);
extern int ps_plot(struct zint_symbol *symbol);
extern int svg_plot(struct zint_symbol *symbol);
void error_tag(char error_string[], int error_number)
{
char error_buffer[100];
if(error_number != 0) {
strcpy(error_buffer, error_string);
if(error_number > 4) {
strcpy(error_string, "error: ");
} else {
strcpy(error_string, "warning: ");
}
concat(error_string, error_buffer);
}
}
int hibc(struct zint_symbol *symbol, unsigned char source[], int length)
{
int counter, error_number, i;
char to_process[40], temp[2], check_digit;
if(length > 36) {
strcpy(symbol->errtxt, "Data too long for HIBC LIC");
return ERROR_TOO_LONG;
}
to_upper(source);
error_number = is_sane(TECHNETIUM , source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
strcpy(to_process, "+");
counter = 41;
for(i = 0; i < length; i++) {
counter += posn(TECHNETIUM, source[i]);
}
counter = counter % 43;
if(counter < 10) {
check_digit = itoc(counter);
} else {
if(counter < 36) {
check_digit = (counter - 10) + 'A';
} else {
switch(counter) {
case 36: check_digit = '-'; break;
case 37: check_digit = '.'; break;
case 38: check_digit = ' '; break;
case 39: check_digit = '$'; break;
case 40: check_digit = '/'; break;
case 41: check_digit = '+'; break;
case 42: check_digit = '%'; break;
default: check_digit = ' '; break; /* Keep compiler happy */
}
}
}
temp[0] = check_digit;
temp[1] = '\0';
concat(to_process, (char *)source);
concat(to_process, temp);
length = strlen(to_process);
switch(symbol->symbology) {
case BARCODE_HIBC_128:
error_number = code_128(symbol, (unsigned char *)to_process, length);
ustrcpy(symbol->text, (unsigned char*)"*");
uconcat(symbol->text, (unsigned char*)to_process);
uconcat(symbol->text, (unsigned char*)"*");
break;
case BARCODE_HIBC_39:
symbol->option_2 = 0;
error_number = c39(symbol, (unsigned char *)to_process, length);
ustrcpy(symbol->text, (unsigned char*)"*");
uconcat(symbol->text, (unsigned char*)to_process);
uconcat(symbol->text, (unsigned char*)"*");
break;
case BARCODE_HIBC_DM:
error_number = dmatrix(symbol, (unsigned char *)to_process, length);
break;
case BARCODE_HIBC_QR:
error_number = qr_code(symbol, (unsigned char *)to_process, length);
break;
case BARCODE_HIBC_PDF:
error_number = pdf417enc(symbol, (unsigned char *)to_process, length);
break;
case BARCODE_HIBC_MICPDF:
error_number = micro_pdf417(symbol, (unsigned char *)to_process, length);
break;
case BARCODE_HIBC_AZTEC:
error_number = aztec(symbol, (unsigned char *)to_process, length);
break;
}
return error_number;
}
int gs1_compliant(int symbology)
{
/* Returns 1 if symbology supports GS1 data */
int result = 0;
switch(symbology) {
case BARCODE_EAN128:
case BARCODE_RSS_EXP:
case BARCODE_RSS_EXPSTACK:
case BARCODE_EANX_CC:
case BARCODE_EAN128_CC:
case BARCODE_RSS14_CC:
case BARCODE_RSS_LTD_CC:
case BARCODE_RSS_EXP_CC:
case BARCODE_UPCA_CC:
case BARCODE_UPCE_CC:
case BARCODE_RSS14STACK_CC:
case BARCODE_RSS14_OMNI_CC:
case BARCODE_RSS_EXPSTACK_CC:
case BARCODE_CODE16K:
case BARCODE_AZTEC:
case BARCODE_DATAMATRIX:
case BARCODE_CODEONE:
case BARCODE_CODE49:
case BARCODE_QRCODE:
result = 1;
break;
}
return result;
}
int ZBarcode_ValidID(int symbol_id)
{
/* Checks whether a symbology is supported */
int result = 0;
switch(symbol_id) {
case BARCODE_CODE11:
case BARCODE_C25MATRIX:
case BARCODE_C25INTER:
case BARCODE_C25IATA:
case BARCODE_C25LOGIC:
case BARCODE_C25IND:
case BARCODE_CODE39:
case BARCODE_EXCODE39:
case BARCODE_EANX:
case BARCODE_EAN128:
case BARCODE_CODABAR:
case BARCODE_CODE128:
case BARCODE_DPLEIT:
case BARCODE_DPIDENT:
case BARCODE_CODE16K:
case BARCODE_CODE49:
case BARCODE_CODE93:
case BARCODE_FLAT:
case BARCODE_RSS14:
case BARCODE_RSS_LTD:
case BARCODE_RSS_EXP:
case BARCODE_TELEPEN:
case BARCODE_UPCA:
case BARCODE_UPCE:
case BARCODE_POSTNET:
case BARCODE_MSI_PLESSEY:
case BARCODE_FIM:
case BARCODE_LOGMARS:
case BARCODE_PHARMA:
case BARCODE_PZN:
case BARCODE_PHARMA_TWO:
case BARCODE_PDF417:
case BARCODE_PDF417TRUNC:
case BARCODE_MAXICODE:
case BARCODE_QRCODE:
case BARCODE_CODE128B:
case BARCODE_AUSPOST:
case BARCODE_AUSREPLY:
case BARCODE_AUSROUTE:
case BARCODE_AUSREDIRECT:
case BARCODE_ISBNX:
case BARCODE_RM4SCC:
case BARCODE_DATAMATRIX:
case BARCODE_EAN14:
case BARCODE_NVE18:
case BARCODE_JAPANPOST:
case BARCODE_KOREAPOST:
case BARCODE_RSS14STACK:
case BARCODE_RSS14STACK_OMNI:
case BARCODE_RSS_EXPSTACK:
case BARCODE_PLANET:
case BARCODE_MICROPDF417:
case BARCODE_ONECODE:
case BARCODE_PLESSEY:
case BARCODE_TELEPEN_NUM:
case BARCODE_ITF14:
case BARCODE_KIX:
case BARCODE_AZTEC:
case BARCODE_DAFT:
case BARCODE_MICROQR:
case BARCODE_HIBC_128:
case BARCODE_HIBC_39:
case BARCODE_HIBC_DM:
case BARCODE_HIBC_QR:
case BARCODE_HIBC_PDF:
case BARCODE_HIBC_MICPDF:
case BARCODE_HIBC_AZTEC:
case BARCODE_AZRUNE:
case BARCODE_CODE32:
case BARCODE_EANX_CC:
case BARCODE_EAN128_CC:
case BARCODE_RSS14_CC:
case BARCODE_RSS_LTD_CC:
case BARCODE_RSS_EXP_CC:
case BARCODE_UPCA_CC:
case BARCODE_UPCE_CC:
case BARCODE_RSS14STACK_CC:
case BARCODE_RSS14_OMNI_CC:
case BARCODE_RSS_EXPSTACK_CC:
case BARCODE_CHANNEL:
case BARCODE_CODEONE:
case BARCODE_GRIDMATRIX:
result = 1;
break;
}
return result;
}
int extended_charset(struct zint_symbol *symbol, unsigned char *source, int length)
{
int error_number = 0;
/* These are the "elite" standards which can support multiple character sets */
switch(symbol->symbology) {
case BARCODE_QRCODE: error_number = qr_code(symbol, source, length); break;
case BARCODE_MICROQR: error_number = microqr(symbol, source, length); break;
case BARCODE_GRIDMATRIX: error_number = grid_matrix(symbol, source, length); break;
}
return error_number;
}
int reduced_charset(struct zint_symbol *symbol, unsigned char *source, int length)
{
/* These are the "norm" standards which only support Latin-1 at most */
int error_number = 0;
#ifndef _MSC_VER
unsigned char preprocessed[length + 1];
#else
unsigned char* preprocessed = (unsigned char*)_alloca(length + 1);
#endif
if(symbol->symbology == BARCODE_CODE16K) {
symbol->whitespace_width = 16;
symbol->border_width = 2;
symbol->output_options = BARCODE_BIND;
}
if(symbol->symbology == BARCODE_ITF14) {
symbol->whitespace_width = 20;
symbol->border_width = 8;
symbol->output_options = BARCODE_BOX;
}
switch(symbol->input_mode) {
case DATA_MODE:
case GS1_MODE:
memcpy(preprocessed, source, length);
preprocessed[length] = '\0';
break;
case UNICODE_MODE:
error_number = latin1_process(symbol, source, preprocessed, &length);
if(error_number != 0) { return error_number; }
break;
}
switch(symbol->symbology) {
case BARCODE_C25MATRIX: error_number = matrix_two_of_five(symbol, preprocessed, length); break;
case BARCODE_C25IND: error_number = industrial_two_of_five(symbol, preprocessed, length); break;
case BARCODE_C25INTER: error_number = interleaved_two_of_five(symbol, preprocessed, length); break;
case BARCODE_C25IATA: error_number = iata_two_of_five(symbol, preprocessed, length); break;
case BARCODE_C25LOGIC: error_number = logic_two_of_five(symbol, preprocessed, length); break;
case BARCODE_DPLEIT: error_number = dpleit(symbol, preprocessed, length); break;
case BARCODE_DPIDENT: error_number = dpident(symbol, preprocessed, length); break;
case BARCODE_UPCA: error_number = eanx(symbol, preprocessed, length); break;
case BARCODE_UPCE: error_number = eanx(symbol, preprocessed, length); break;
case BARCODE_EANX: error_number = eanx(symbol, preprocessed, length); break;
case BARCODE_EAN128: error_number = ean_128(symbol, preprocessed, length); break;
case BARCODE_CODE39: error_number = c39(symbol, preprocessed, length); break;
case BARCODE_PZN: error_number = pharmazentral(symbol, preprocessed, length); break;
case BARCODE_EXCODE39: error_number = ec39(symbol, preprocessed, length); break;
case BARCODE_CODABAR: error_number = codabar(symbol, preprocessed, length); break;
case BARCODE_CODE93: error_number = c93(symbol, preprocessed, length); break;
case BARCODE_LOGMARS: error_number = c39(symbol, preprocessed, length); break;
case BARCODE_CODE128: error_number = code_128(symbol, preprocessed, length); break;
case BARCODE_CODE128B: error_number = code_128(symbol, preprocessed, length); break;
case BARCODE_NVE18: error_number = nve_18(symbol, preprocessed, length); break;
case BARCODE_CODE11: error_number = code_11(symbol, preprocessed, length); break;
case BARCODE_MSI_PLESSEY: error_number = msi_handle(symbol, preprocessed, length); break;
case BARCODE_TELEPEN: error_number = telepen(symbol, preprocessed, length); break;
case BARCODE_TELEPEN_NUM: error_number = telepen_num(symbol, preprocessed, length); break;
case BARCODE_PHARMA: error_number = pharma_one(symbol, preprocessed, length); break;
case BARCODE_PLESSEY: error_number = plessey(symbol, preprocessed, length); break;
case BARCODE_ITF14: error_number = itf14(symbol, preprocessed, length); break;
case BARCODE_FLAT: error_number = flattermarken(symbol, preprocessed, length); break;
case BARCODE_FIM: error_number = fim(symbol, preprocessed, length); break;
case BARCODE_POSTNET: error_number = post_plot(symbol, preprocessed, length); break;
case BARCODE_PLANET: error_number = planet_plot(symbol, preprocessed, length); break;
case BARCODE_RM4SCC: error_number = royal_plot(symbol, preprocessed, length); break;
case BARCODE_AUSPOST: error_number = australia_post(symbol, preprocessed, length); break;
case BARCODE_AUSREPLY: error_number = australia_post(symbol, preprocessed, length); break;
case BARCODE_AUSROUTE: error_number = australia_post(symbol, preprocessed, length); break;
case BARCODE_AUSREDIRECT: error_number = australia_post(symbol, preprocessed, length); break;
case BARCODE_CODE16K: error_number = code16k(symbol, preprocessed, length); break;
case BARCODE_PHARMA_TWO: error_number = pharma_two(symbol, preprocessed, length); break;
case BARCODE_ONECODE: error_number = imail(symbol, preprocessed, length); break;
case BARCODE_ISBNX: error_number = eanx(symbol, preprocessed, length); break;
case BARCODE_RSS14: error_number = rss14(symbol, preprocessed, length); break;
case BARCODE_RSS14STACK: error_number = rss14(symbol, preprocessed, length); break;
case BARCODE_RSS14STACK_OMNI: error_number = rss14(symbol, preprocessed, length); break;
case BARCODE_RSS_LTD: error_number = rsslimited(symbol, preprocessed, length); break;
case BARCODE_RSS_EXP: error_number = rssexpanded(symbol, preprocessed, length); break;
case BARCODE_RSS_EXPSTACK: error_number = rssexpanded(symbol, preprocessed, length); break;
case BARCODE_EANX_CC: error_number = composite(symbol, preprocessed, length); break;
case BARCODE_EAN128_CC: error_number = composite(symbol, preprocessed, length); break;
case BARCODE_RSS14_CC: error_number = composite(symbol, preprocessed, length); break;
case BARCODE_RSS_LTD_CC: error_number = composite(symbol, preprocessed, length); break;
case BARCODE_RSS_EXP_CC: error_number = composite(symbol, preprocessed, length); break;
case BARCODE_UPCA_CC: error_number = composite(symbol, preprocessed, length); break;
case BARCODE_UPCE_CC: error_number = composite(symbol, preprocessed, length); break;
case BARCODE_RSS14STACK_CC: error_number = composite(symbol, preprocessed, length); break;
case BARCODE_RSS14_OMNI_CC: error_number = composite(symbol, preprocessed, length); break;
case BARCODE_RSS_EXPSTACK_CC: error_number = composite(symbol, preprocessed, length); break;
case BARCODE_KIX: error_number = kix_code(symbol, preprocessed, length); break;
case BARCODE_CODE32: error_number = code32(symbol, preprocessed, length); break;
case BARCODE_DAFT: error_number = daft_code(symbol, preprocessed, length); break;
case BARCODE_EAN14: error_number = ean_14(symbol, preprocessed, length); break;
case BARCODE_AZRUNE: error_number = aztec_runes(symbol, preprocessed, length); break;
case BARCODE_KOREAPOST: error_number = korea_post(symbol, preprocessed, length); break;
case BARCODE_HIBC_128: error_number = hibc(symbol, preprocessed, length); break;
case BARCODE_HIBC_39: error_number = hibc(symbol, preprocessed, length); break;
case BARCODE_HIBC_DM: error_number = hibc(symbol, preprocessed, length); break;
case BARCODE_HIBC_QR: error_number = hibc(symbol, preprocessed, length); break;
case BARCODE_HIBC_PDF: error_number = hibc(symbol, preprocessed, length); break;
case BARCODE_HIBC_MICPDF: error_number = hibc(symbol, preprocessed, length); break;
case BARCODE_HIBC_AZTEC: error_number = hibc(symbol, preprocessed, length); break;
case BARCODE_JAPANPOST: error_number = japan_post(symbol, preprocessed, length); break;
case BARCODE_CODE49: error_number = code_49(symbol, preprocessed, length); break;
case BARCODE_CHANNEL: error_number = channel_code(symbol, preprocessed, length); break;
case BARCODE_CODEONE: error_number = code_one(symbol, preprocessed, length); break;
case BARCODE_DATAMATRIX: error_number = dmatrix(symbol, preprocessed, length); break;
case BARCODE_PDF417: error_number = pdf417enc(symbol, preprocessed, length); break;
case BARCODE_PDF417TRUNC: error_number = pdf417enc(symbol, preprocessed, length); break;
case BARCODE_MICROPDF417: error_number = micro_pdf417(symbol, preprocessed, length); break;
case BARCODE_MAXICODE: error_number = maxicode(symbol, preprocessed, length); break;
case BARCODE_AZTEC: error_number = aztec(symbol, preprocessed, length); break;
}
return error_number;
}
int ZBarcode_Encode(struct zint_symbol *symbol, unsigned char *source, int length)
{
int error_number, error_buffer, i;
error_number = 0;
if(length == 0) {
length = ustrlen(source);
}
if(length == 0) {
strcpy(symbol->errtxt, "No input data");
error_tag(symbol->errtxt, ERROR_INVALID_DATA);
return ERROR_INVALID_DATA;
}
#ifndef _MSC_VER
unsigned char local_source[length + 1];
#else
unsigned char* local_source = (unsigned char*)_alloca(length + 1);
#endif
/* First check the symbology field */
if(symbol->symbology < 1) { strcpy(symbol->errtxt, "Symbology out of range, using Code 128"); symbol->symbology = BARCODE_CODE128; error_number = WARN_INVALID_OPTION; }
/* symbol->symbologys 1 to 86 are defined by tbarcode */
if(symbol->symbology == 5) { symbol->symbology = BARCODE_C25MATRIX; }
if((symbol->symbology >= 10) && (symbol->symbology <= 12)) { symbol->symbology = BARCODE_EANX; }
if((symbol->symbology == 14) || (symbol->symbology == 15)) { symbol->symbology = BARCODE_EANX; }
if(symbol->symbology == 17) { symbol->symbology = BARCODE_UPCA; }
if(symbol->symbology == 19) { strcpy(symbol->errtxt, "Codabar 18 not supported, using Codabar"); symbol->symbology = BARCODE_CODABAR; error_number = WARN_INVALID_OPTION; }
if(symbol->symbology == 26) { symbol->symbology = BARCODE_UPCA; }
if(symbol->symbology == 27) { strcpy(symbol->errtxt, "UPCD1 not supported"); error_number = ERROR_INVALID_OPTION; }
if(symbol->symbology == 33) { symbol->symbology = BARCODE_EAN128; }
if((symbol->symbology == 35) || (symbol->symbology == 36)) { symbol->symbology = BARCODE_UPCA; }
if((symbol->symbology == 38) || (symbol->symbology == 39)) { symbol->symbology = BARCODE_UPCE; }
if((symbol->symbology >= 41) && (symbol->symbology <= 45)) { symbol->symbology = BARCODE_POSTNET; }
if(symbol->symbology == 46) { symbol->symbology = BARCODE_PLESSEY; }
if(symbol->symbology == 48) { symbol->symbology = BARCODE_NVE18; }
if(symbol->symbology == 54) { strcpy(symbol->errtxt, "General Parcel Code not supported, using Code 128"); symbol->symbology = BARCODE_CODE128; error_number = WARN_INVALID_OPTION; }
if((symbol->symbology == 59) || (symbol->symbology == 61)) { symbol->symbology = BARCODE_CODE128; }
if(symbol->symbology == 62) { symbol->symbology = BARCODE_CODE93; }
if((symbol->symbology == 64) || (symbol->symbology == 65)) { symbol->symbology = BARCODE_AUSPOST; }
if(symbol->symbology == 73) { strcpy(symbol->errtxt, "Codablock E not supported"); error_number = ERROR_INVALID_OPTION; }
if(symbol->symbology == 78) { symbol->symbology = BARCODE_RSS14; }
if(symbol->symbology == 83) { symbol->symbology = BARCODE_PLANET; }
if(symbol->symbology == 88) { symbol->symbology = BARCODE_EAN128; }
if(symbol->symbology == 91) { strcpy(symbol->errtxt, "Symbology out of range, using Code 128"); symbol->symbology = BARCODE_CODE128; error_number = WARN_INVALID_OPTION; }
if((symbol->symbology >= 94) && (symbol->symbology <= 96)) { strcpy(symbol->errtxt, "Symbology out of range, using Code 128"); symbol->symbology = BARCODE_CODE128; error_number = WARN_INVALID_OPTION; }
if(symbol->symbology == 100) { symbol->symbology = BARCODE_HIBC_128; }
if(symbol->symbology == 101) { symbol->symbology = BARCODE_HIBC_39; }
if(symbol->symbology == 103) { symbol->symbology = BARCODE_HIBC_DM; }
if(symbol->symbology == 105) { symbol->symbology = BARCODE_HIBC_QR; }
if(symbol->symbology == 107) { symbol->symbology = BARCODE_HIBC_PDF; }
if(symbol->symbology == 109) { symbol->symbology = BARCODE_HIBC_MICPDF; }
if(symbol->symbology == 111) { symbol->symbology = BARCODE_HIBC_BLOCKF; }
if((symbol->symbology >= 113) && (symbol->symbology <= 127)) { strcpy(symbol->errtxt, "Symbology out of range, using Code 128"); symbol->symbology = BARCODE_CODE128; error_number = WARN_INVALID_OPTION; }
/* Everything from 128 up is Zint-specific */
if(symbol->symbology >= 143) { strcpy(symbol->errtxt, "Symbology out of range, using Code 128"); symbol->symbology = BARCODE_CODE128; error_number = WARN_INVALID_OPTION; }
if((symbol->symbology == BARCODE_CODABLOCKF) || (symbol->symbology == BARCODE_HIBC_BLOCKF)) { strcpy(symbol->errtxt, "Codablock F not supported"); error_number = ERROR_INVALID_OPTION; }
if(error_number > 4) {
error_tag(symbol->errtxt, error_number);
return error_number;
} else {
error_buffer = error_number;
}
if((symbol->input_mode < 0) || (symbol->input_mode > 2)) { symbol->input_mode = DATA_MODE; }
if(symbol->input_mode == GS1_MODE) {
for(i = 0; i < length; i++) {
if(source[i] == '\0') {
strcpy(symbol->errtxt, "NULL characters not permitted in GS1 mode");
return ERROR_INVALID_DATA;
}
}
if(gs1_compliant(symbol->symbology) == 1) {
error_number = ugs1_verify(symbol, source, length, local_source);
if(error_number != 0) { return error_number; }
length = ustrlen(local_source);
} else {
strcpy(symbol->errtxt, "Selected symbology does not support GS1 mode");
return ERROR_INVALID_OPTION;
}
} else {
memcpy(local_source, source, length);
local_source[length] = '\0';
}
switch(symbol->symbology) {
case BARCODE_QRCODE:
case BARCODE_MICROQR:
case BARCODE_GRIDMATRIX:
error_number = extended_charset(symbol, local_source, length);
break;
default:
error_number = reduced_charset(symbol, local_source, length);
break;
}
if((symbol->symbology == BARCODE_CODE128) || (symbol->symbology == BARCODE_CODE128B)) {
for(i = 0; i < length; i++) {
if(local_source[i] == '\0') {
symbol->text[i] = ' ';
} else {
symbol->text[i] = local_source[i];
}
}
}
if(error_number == 0) {
error_number = error_buffer;
}
error_tag(symbol->errtxt, error_number);
/*printf("%s\n",symbol->text);*/
return error_number;
}
int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle)
{
int error_number;
char output[4];
switch(rotate_angle) {
case 0:
case 90:
case 180:
case 270:
break;
default:
strcpy(symbol->errtxt, "Invalid rotation angle");
return ERROR_INVALID_OPTION;
break;
}
if(strlen(symbol->outfile) > 3) {
output[0] = symbol->outfile[strlen(symbol->outfile) - 3];
output[1] = symbol->outfile[strlen(symbol->outfile) - 2];
output[2] = symbol->outfile[strlen(symbol->outfile) - 1];
output[3] = '\0';
to_upper((unsigned char*)output);
#ifndef NO_PNG
if(!(strcmp(output, "PNG"))) {
if(symbol->scale < 1.0) { symbol->text[0] = '\0'; }
error_number = png_handle(symbol, rotate_angle);
} else {
#endif
if(!(strcmp(output, "EPS"))) {
error_number = ps_plot(symbol);
} else {
if(!(strcmp(output, "SVG"))) {
error_number = svg_plot(symbol);
} else {
strcpy(symbol->errtxt, "Unknown output format");
error_tag(symbol->errtxt, ERROR_INVALID_OPTION);
return ERROR_INVALID_OPTION;
}
}
#ifndef NO_PNG
}
#endif
} else {
strcpy(symbol->errtxt, "Unknown output format");
error_tag(symbol->errtxt, ERROR_INVALID_OPTION);
return ERROR_INVALID_OPTION;
}
error_tag(symbol->errtxt, error_number);
return error_number;
}
int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle)
{
int error_number;
switch(rotate_angle) {
case 0:
case 90:
case 180:
case 270:
break;
default:
strcpy(symbol->errtxt, "Invalid rotation angle");
return ERROR_INVALID_OPTION;
break;
}
error_number = bmp_handle(symbol, rotate_angle);
error_tag(symbol->errtxt, error_number);
return error_number;
}
int ZBarcode_Print_Rotated(struct zint_symbol *symbol, int rotate_angle) {
/* Depreciated - will be removed in later version */
return ZBarcode_Print(symbol, rotate_angle);
}
int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, unsigned char *input, int length, int rotate_angle)
{
int error_number;
error_number = 0;
error_number = ZBarcode_Encode(symbol, input, length);
if(error_number != 0) {
return error_number;
}
error_number = ZBarcode_Print(symbol, rotate_angle);
return error_number;
}
int ZBarcode_Encode_and_Buffer(struct zint_symbol *symbol, unsigned char *input, int length, int rotate_angle)
{
int error_number;
error_number = 0;
error_number = ZBarcode_Encode(symbol, input, length);
if(error_number != 0) {
return error_number;
}
error_number = ZBarcode_Buffer(symbol, rotate_angle);
return error_number;
}
int ZBarcode_Encode_and_Print_Rotated(struct zint_symbol *symbol, unsigned char *input, int rotate_angle) {
/* Depreciated - will be removed in later version */
return ZBarcode_Encode_and_Print(symbol, input, rotate_angle, strlen((char *)input));
}
int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename)
{
FILE *file;
unsigned char *buffer;
unsigned long fileLen;
unsigned int nRead = 0, n = 0;
int ret;
file = fopen(filename, "rb");
if (!file) {
strcpy(symbol->errtxt, "Unable to read input file");
return ERROR_INVALID_DATA;
}
/* Get file length */
fseek(file, 0, SEEK_END);
fileLen = ftell(file);
fseek(file, 0, SEEK_SET);
if(fileLen > 7100) {
/* The largest amount of data that can be encoded is 7089 numeric digits in QR Code */
strcpy(symbol->errtxt, "Input file too long");
fclose(file);
return ERROR_INVALID_DATA;
}
/* Allocate memory */
buffer = (unsigned char *)malloc(fileLen * sizeof(unsigned char));
if(!buffer) {
strcpy(symbol->errtxt, "Internal memory error");
fclose(file);
return ERROR_MEMORY;
}
/* Read file contents into buffer */
do
{
n = fread(buffer + nRead, 1, fileLen - nRead, file);
if (ferror(file))
{
strcpy(symbol->errtxt, strerror(errno));
nRead = 0;
return ERROR_INVALID_DATA;
}
nRead += n;
} while (!feof(file) && (0 < n) && (nRead < fileLen));
fclose(file);
ret = ZBarcode_Encode(symbol, buffer, nRead);
free(buffer);
return ret;
}
int ZBarcode_Encode_File_and_Print(struct zint_symbol *symbol, char *filename, int rotate_angle)
{
int error_number;
error_number = 0;
error_number = ZBarcode_Encode_File(symbol, filename);
if(error_number != 0) {
return error_number;
}
return ZBarcode_Print(symbol, rotate_angle);
}
int ZBarcode_Encode_File_and_Buffer(struct zint_symbol *symbol, char *filename, int rotate_angle)
{
int error_number;
error_number = 0;
error_number = ZBarcode_Encode_File(symbol, filename);
if(error_number != 0) {
return error_number;
}
return ZBarcode_Buffer(symbol, rotate_angle);
}

42
backend/libzint.rc Normal file
View file

@ -0,0 +1,42 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winver.h>
#ifdef GCC_WINDRES
VS_VERSION_INFO VERSIONINFO
#else
VS_VERSION_INFO VERSIONINFO
#endif
FILEVERSION 2,3,0,0
PRODUCTVERSION 2,3,0,0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0
#endif
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
//language ID = U.S. English, char set = Windows, Multilingual
BEGIN
VALUE "FileDescription", "libzint barcode library\0"
VALUE "FileVersion", "2.3.0.0\0"
VALUE "InternalName", "zint.dll\0"
VALUE "LegalCopyright", "Copyright © 2009 Robin Stuart & BogDan Vatra\0"
VALUE "OriginalFilename", "zint.dll\0"
VALUE "ProductName", "libzint\0"
VALUE "ProductVersion", "2.3.0.0\0"
VALUE "License", "GNU General Public License version 3\0"
VALUE "WWW", "http://www.sourceforge.net/projects/zint\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 1250
END
END

702
backend/maxicode.c Normal file
View file

@ -0,0 +1,702 @@
/* maxicode.c - Handles Maxicode */
/*
libzint - the open source barcode library
Copyright (C) 2010 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* Includes corrections thanks to Monica Swanson @ Source Technologies */
#include "common.h"
#include "maxicode.h"
#include "reedsol.h"
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
int maxi_codeword[144];
void maxi_do_primary_check( )
{
/* Handles error correction of primary message */
unsigned char data[15];
unsigned char results[15];
int j;
int datalen = 10;
int ecclen = 10;
rs_init_gf(0x43);
rs_init_code(ecclen, 1);
for(j = 0; j < datalen; j += 1)
data[j] = maxi_codeword[j];
rs_encode(datalen, data, results);
for ( j = 0; j < ecclen; j += 1)
maxi_codeword[ datalen + j] = results[ecclen - 1 - j];
rs_free();
}
void maxi_do_secondary_chk_odd( int ecclen )
{
/* Handles error correction of odd characters in secondary */
unsigned char data[100];
unsigned char results[30];
int j;
int datalen = 68;
rs_init_gf(0x43);
rs_init_code(ecclen, 1);
if (ecclen == 20)
datalen = 84;
for(j = 0; j < datalen; j += 1)
if ((j % 2) == 1) // odd
data[(j-1)/2] = maxi_codeword[j + 20];
rs_encode(datalen/2, data, results);
for ( j = 0; j < (ecclen); j += 1)
maxi_codeword[ datalen + (2 *j) + 1 + 20 ] = results[ecclen - 1 - j];
rs_free();
}
void maxi_do_secondary_chk_even(int ecclen )
{
/* Handles error correction of even characters in secondary */
unsigned char data[100];
unsigned char results[30];
int j;
int datalen = 68;
if (ecclen == 20)
datalen = 84;
rs_init_gf(0x43);
rs_init_code(ecclen, 1);
for(j = 0; j < datalen + 1; j += 1)
if ((j % 2) == 0) // even
data[j/2] = maxi_codeword[j + 20];
rs_encode(datalen/2, data, results);
for ( j = 0; j < (ecclen); j += 1)
maxi_codeword[ datalen + (2 *j) + 20] = results[ecclen - 1 - j];
rs_free();
}
void maxi_bump(int set[], int character[], int bump_posn)
{
/* Moves everything up so that a shift or latch can be inserted */
int i;
for(i = 143; i > bump_posn; i--) {
set[i] = set[i - 1];
character[i] = character[i - 1];
}
}
int maxi_text_process(int mode, unsigned char source[], int length)
{
/* Format text according to Appendix A */
/* This code doesn't make use of [Lock in C], [Lock in D]
and [Lock in E] and so is not always the most efficient at
compressing data, but should suffice for most applications */
int set[144], character[144], i, j, done, count, current_set;
if(length > 138) {
return ERROR_TOO_LONG;
}
for(i = 0; i < 144; i++) {
set[i] = -1;
character[i] = 0;
}
for (i = 0; i < length; i++) {
/* Look up characters in table from Appendix A - this gives
value and code set for most characters */
set[i] = maxiCodeSet[source[i]];
character[i] = maxiSymbolChar[source[i]];
}
/* If a character can be represented in more than one code set,
pick which version to use */
if(set[0] == 0) {
if(character[0] == 13) {
character[0] = 0;
}
set[0] = 1;
}
for(i = 1; i < length; i++) {
if(set[i] == 0) {
done = 0;
/* Special character */
if(character[i] == 13) {
/* Carriage Return */
if(set[i - 1] == 5) {
character[i] = 13;
set[i] = 5;
} else {
if((i != length - 1) && (set[i + 1] == 5)) {
character[i] = 13;
set[i] = 5;
} else {
character[i] = 0;
set[i] = 1;
}
}
done = 1;
}
if((character[i] == 28) && (done == 0)) {
/* FS */
if(set[i - 1] == 5) {
character[i] = 32;
set[i] = 5;
} else {
set[i] = set[i - 1];
}
done = 1;
}
if((character[i] == 29) && (done == 0)) {
/* GS */
if(set[i - 1] == 5) {
character[i] = 33;
set[i] = 5;
} else {
set[i] = set[i - 1];
}
done = 1;
}
if((character[i] == 30) && (done == 0)) {
/* RS */
if(set[i - 1] == 5) {
character[i] = 34;
set[i] = 5;
} else {
set[i] = set[i - 1];
}
done = 1;
}
if((character[i] == 32) && (done == 0)) {
/* Space */
if(set[i - 1] == 1) {
character[i] = 32;
set[i] = 1;
}
if(set[i - 1] == 2) {
character[i] = 47;
set[i] = 2;
}
if(set[i - 1] >= 3) {
if(i != length - 1) {
if(set[i + 1] == 1) {
character[i] = 32;
set[i] = 1;
}
if(set[i + 1] == 2) {
character[i] = 47;
set[i] = 2;
}
if(set[i + 1] >= 3) {
character[i] = 59;
set[i] = set[i - 1];
}
} else {
character[i] = 59;
set[i] = set[i - 1];
}
}
done = 1;
}
if((character[i] == 44) && (done == 0)) {
/* Comma */
if(set[i - 1] == 2) {
character[i] = 48;
set[i] = 2;
} else {
if((i != length - 1) && (set[i + 1] == 2)) {
character[i] = 48;
set[i] = 2;
} else {
set[i] = 1;
}
}
done = 1;
}
if((character[i] == 46) && (done == 0)) {
/* Full Stop */
if(set[i - 1] == 2) {
character[i] = 49;
set[i] = 2;
} else {
if((i != length - 1) && (set[i + 1] == 2)) {
character[i] = 49;
set[i] = 2;
} else {
set[i] = 1;
}
}
done = 1;
}
if((character[i] == 47) && (done == 0)) {
/* Slash */
if(set[i - 1] == 2) {
character[i] = 50;
set[i] = 2;
} else {
if((i != length - 1) && (set[i + 1] == 2)) {
character[i] = 50;
set[i] = 2;
} else {
set[i] = 1;
}
}
done = 1;
}
if((character[i] == 58) && (done == 0)) {
/* Colon */
if(set[i - 1] == 2) {
character[i] = 51;
set[i] = 2;
} else {
if((i != length - 1) && (set[i + 1] == 2)) {
character[i] = 51;
set[i] = 2;
} else {
set[i] = 1;
}
}
done = 1;
}
}
}
for(i = length; i < 144; i++) {
/* Add the padding */
if(set[length - 1] == 2) {
set[i] = 2;
} else {
set[i] = 1;
}
character[i] = 33;
}
/* Find candidates for number compression */
if((mode == 2) || (mode ==3)) { j = 0; } else { j = 9; }
/* Number compression not allowed in primary message */
count = 0;
for(i = j; i < 143; i++) {
if((set[i] == 1) && ((character[i] >= 48) && (character[i] <= 57))) {
/* Character is a number */
count++;
} else {
count = 0;
}
if(count == 9) {
/* Nine digits in a row can be compressed */
set[i] = 6;
set[i - 1] = 6;
set[i - 2] = 6;
set[i - 3] = 6;
set[i - 4] = 6;
set[i - 5] = 6;
set[i - 6] = 6;
set[i - 7] = 6;
set[i - 8] = 6;
count = 0;
}
}
/* Add shift and latch characters */
current_set = 1;
i = 0;
do {
if(set[i] != current_set) {
switch(set[i]) {
case 1:
if(set[i + 1] == 1) {
if(set[i + 2] == 1) {
if(set[i + 3] == 1) {
/* Latch A */
maxi_bump(set, character, i);
character[i] = 63;
current_set = 1;
length++;
} else {
/* 3 Shift A */
maxi_bump(set, character, i);
character[i] = 57;
length++;
i += 2;
}
} else {
/* 2 Shift A */
maxi_bump(set, character, i);
character[i] = 56;
length++;
i++;
}
} else {
/* Shift A */
maxi_bump(set, character, i);
character[i] = 59;
length++;
}
break;
case 2:
if(set[i + 1] == 2) {
/* Latch B */
maxi_bump(set, character, i);
character[i] = 63;
current_set = 2;
length++;
} else {
/* Shift B */
maxi_bump(set, character, i);
character[i] = 59;
length++;
}
break;
case 3:
/* Shift C */
maxi_bump(set, character, i);
character[i] = 60;
length++;
break;
case 4:
/* Shift D */
maxi_bump(set, character, i);
character[i] = 61;
length++;
break;
case 5:
/* Shift E */
maxi_bump(set, character, i);
character[i] = 62;
length++;
break;
case 6:
/* Number Compressed */
/* Do nothing */
break;
}
i++;
}
i++;
} while(i < 145);
/* Number compression has not been forgotten! - It's handled below */
i = 0;
do {
if (set[i] == 6) {
/* Number compression */
char substring[11];
int value;
for(j = 0; j < 10; j++) {
substring[j] = character[i + j];
}
substring[10] = '\0';
value = atoi(substring);
character[i] = 31; /* NS */
character[i + 1] = (value & 0x3f000000) >> 24;
character[i + 2] = (value & 0xfc0000) >> 18;
character[i + 3] = (value & 0x3f000) >> 12;
character[i + 4] = (value & 0xfc0) >> 6;
character[i + 5] = (value & 0x3f);
i += 6;
for(j = i; j < 140; j++) {
set[j] = set[j + 3];
character[j] = character[j + 3];
}
length -= 3;
} else {
i++;
}
} while (i <= 143);
if(((mode ==2) || (mode == 3)) && (length > 84)) {
return ERROR_TOO_LONG;
}
if(((mode == 4) || (mode == 6)) && (length > 93)) {
return ERROR_TOO_LONG;
}
if((mode == 5) && (length > 77)) {
return ERROR_TOO_LONG;
}
/* Copy the encoded text into the codeword array */
if((mode == 2) || (mode == 3)) {
for(i = 0; i < 84; i++) { /* secondary only */
maxi_codeword[i + 20] = character[i];
}
}
if((mode == 4) || (mode == 6)) {
for(i = 0; i < 9; i++) { /* primary */
maxi_codeword[i + 1] = character[i];
}
for(i = 0; i < 84; i++) { /* secondary */
maxi_codeword[i + 20] = character[i + 9];
}
}
if(mode == 5) {
for(i = 0; i < 9; i++) { /* primary */
maxi_codeword[i + 1] = character[i];
}
for(i = 0; i < 68; i++) { /* secondary */
maxi_codeword[i + 20] = character[i + 9];
}
}
return 0;
}
void maxi_do_primary_2(char postcode[], int country, int service)
{
/* Format structured primary for Mode 2 */
int postcode_length, postcode_num, i;
for(i = 0; i < 10; i++) {
if((postcode[i] < '0') || (postcode[i] > '9')) {
postcode[i] = '\0';
}
}
postcode_length = strlen(postcode);
postcode_num = atoi(postcode);
maxi_codeword[0] = ((postcode_num & 0x03) << 4) | 2;
maxi_codeword[1] = ((postcode_num & 0xfc) >> 2);
maxi_codeword[2] = ((postcode_num & 0x3f00) >> 8);
maxi_codeword[3] = ((postcode_num & 0xfc000) >> 14);
maxi_codeword[4] = ((postcode_num & 0x3f00000) >> 20);
maxi_codeword[5] = ((postcode_num & 0x3c000000) >> 26) | ((postcode_length & 0x3) << 4);
maxi_codeword[6] = ((postcode_length & 0x3c) >> 2) | ((country & 0x3) << 4);
maxi_codeword[7] = (country & 0xfc) >> 2;
maxi_codeword[8] = ((country & 0x300) >> 8) | ((service & 0xf) << 2);
maxi_codeword[9] = ((service & 0x3f0) >> 4);
}
void maxi_do_primary_3(char postcode[], int country, int service)
{
/* Format structured primary for Mode 3 */
int i, h;
h = strlen(postcode);
to_upper((unsigned char*)postcode);
for(i = 0; i < h; i++) {
if((postcode[i] >= 'A') && (postcode[i] <= 'Z')) {
/* (Capital) letters shifted to Code Set A values */
postcode[i] -= 64;
}
if(((postcode[i] == 27) || (postcode[i] == 31)) || ((postcode[i] == 33) || (postcode[i] >= 59))) {
/* Not a valid postcode character */
postcode[i] = ' ';
}
/* Input characters lower than 27 (NUL - SUB) in postcode are
interpreted as capital letters in Code Set A (e.g. LF becomes 'J') */
}
maxi_codeword[0] = ((postcode[5] & 0x03) << 4) | 3;
maxi_codeword[1] = ((postcode[4] & 0x03) << 4) | ((postcode[5] & 0x3c) >> 2);
maxi_codeword[2] = ((postcode[3] & 0x03) << 4) | ((postcode[4] & 0x3c) >> 2);
maxi_codeword[3] = ((postcode[2] & 0x03) << 4) | ((postcode[3] & 0x3c) >> 2);
maxi_codeword[4] = ((postcode[1] & 0x03) << 4) | ((postcode[2] & 0x3c) >> 2);
maxi_codeword[5] = ((postcode[0] & 0x03) << 4) | ((postcode[1] & 0x3c) >> 2);
maxi_codeword[6] = ((postcode[0] & 0x3c) >> 2) | ((country & 0x3) << 4);
maxi_codeword[7] = (country & 0xfc) >> 2;
maxi_codeword[8] = ((country & 0x300) >> 8) | ((service & 0xf) << 2);
maxi_codeword[9] = ((service & 0x3f0) >> 4);
}
int maxicode(struct zint_symbol *symbol, unsigned char source[], int length)
{
int i, j, block, bit, mode, countrycode = 0, service = 0, lp = 0;
int bit_pattern[7], internal_error = 0, eclen, error_number;
char postcode[12], countrystr[4], servicestr[4];
#ifndef _MSC_VER
unsigned char local_source[length + 1];
#else
unsigned char* local_source = (unsigned char*)_alloca(length + 1);
#endif
mode = symbol->option_1;
strcpy(postcode, "");
strcpy(countrystr, "");
strcpy(servicestr, "");
/* The following to be replaced by ECI handling */
switch(symbol->input_mode) {
case DATA_MODE:
case GS1_MODE:
memcpy(local_source, source, length);
local_source[length] = '\0';
break;
case UNICODE_MODE:
error_number = latin1_process(symbol, source, local_source, &length);
if(error_number != 0) { return error_number; }
break;
}
memset(maxi_codeword, 0, sizeof(maxi_codeword));
if(mode == -1) { /* If mode is unspecified */
lp = strlen(symbol->primary);
if(lp == 0) {
mode = 4;
} else {
mode = 2;
for(i = 0; i < 10 && i < lp; i++) {
if((symbol->primary[i] < 48) || (symbol->primary[i] > 57)) {
mode = 3;
break;
}
}
}
}
if((mode < 2) || (mode > 6)) { /* Only codes 2 to 6 supported */
strcpy(symbol->errtxt, "Invalid Maxicode Mode");
return ERROR_INVALID_OPTION;
}
if((mode == 2) || (mode == 3)) { /* Modes 2 and 3 need data in symbol->primary */
if(lp != 15) {
strcpy(symbol->errtxt, "Invalid Primary String");
return ERROR_INVALID_DATA;
}
for(i = 9; i < 15; i++) { /* check that country code and service are numeric */
if((symbol->primary[i] < '0') || (symbol->primary[i] > '9')) {
strcpy(symbol->errtxt, "Invalid Primary String");
return ERROR_INVALID_DATA;
}
}
memcpy(postcode, symbol->primary, 9);
postcode[9] = '\0';
if(mode == 2) {
for(i = 0; i < 10; i++) {
if(postcode[i] == ' ') {
postcode[i] = '\0';
}
}
}
else if(mode == 3) { postcode[6] = '\0'; }
countrystr[0] = symbol->primary[9];
countrystr[1] = symbol->primary[10];
countrystr[2] = symbol->primary[11];
countrystr[3] = '\0';
servicestr[0] = symbol->primary[12];
servicestr[1] = symbol->primary[13];
servicestr[2] = symbol->primary[14];
servicestr[3] = '\0';
countrycode = atoi(countrystr);
service = atoi(servicestr);
if(mode == 2) { maxi_do_primary_2(postcode, countrycode, service); }
if(mode == 3) { maxi_do_primary_3(postcode, countrycode, service); }
} else {
maxi_codeword[0] = mode;
}
i = maxi_text_process(mode, local_source, length);
if(i == ERROR_TOO_LONG ) {
strcpy(symbol->errtxt, "Input data too long");
return i;
}
/* All the data is sorted - now do error correction */
maxi_do_primary_check(); /* always EEC */
if ( mode == 5 )
eclen = 56; // 68 data codewords , 56 error corrections
else
eclen = 40; // 84 data codewords, 40 error corrections
maxi_do_secondary_chk_even(eclen/2); // do error correction of even
maxi_do_secondary_chk_odd(eclen/2); // do error correction of odd
/* Copy data into symbol grid */
for(i = 0; i < 33; i++) {
for(j = 0; j < 30; j++) {
block = (MaxiGrid[(i * 30) + j] + 5) / 6;
bit = (MaxiGrid[(i * 30) + j] + 5) % 6;
if(block != 0) {
bit_pattern[0] = (maxi_codeword[block - 1] & 0x20) >> 5;
bit_pattern[1] = (maxi_codeword[block - 1] & 0x10) >> 4;
bit_pattern[2] = (maxi_codeword[block - 1] & 0x8) >> 3;
bit_pattern[3] = (maxi_codeword[block - 1] & 0x4) >> 2;
bit_pattern[4] = (maxi_codeword[block - 1] & 0x2) >> 1;
bit_pattern[5] = (maxi_codeword[block - 1] & 0x1);
if(bit_pattern[bit] != 0) {
set_module(symbol, i, j);
}
}
}
}
/* Add orientation markings */
set_module(symbol, 0, 28); // Top right filler
set_module(symbol, 0, 29);
set_module(symbol, 9, 10); // Top left marker
set_module(symbol, 9, 11);
set_module(symbol, 10, 11);
set_module(symbol, 15, 7); // Left hand marker
set_module(symbol, 16, 8);
set_module(symbol, 16, 20); // Right hand marker
set_module(symbol, 17, 20);
set_module(symbol, 22, 10); // Bottom left marker
set_module(symbol, 23, 10);
set_module(symbol, 22, 17); // Bottom right marker
set_module(symbol, 23, 17);
symbol->width = 30;
symbol->rows = 33;
return internal_error;
}

90
backend/maxicode.h Normal file
View file

@ -0,0 +1,90 @@
/* maxicode.h - Handles Maxicode */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
static int MaxiGrid[] = { /* ISO/IEC 16023 Figure 5 - MaxiCode Module Sequence */ /* 30 x 33 data grid */
122, 121, 128, 127, 134, 133, 140, 139, 146, 145, 152, 151, 158, 157, 164, 163, 170, 169, 176, 175, 182, 181, 188, 187, 194, 193, 200, 199, 0, 0,
124, 123, 130, 129, 136, 135, 142, 141, 148, 147, 154, 153, 160, 159, 166, 165, 172, 171, 178, 177, 184, 183, 190, 189, 196, 195, 202, 201, 817, 0,
126, 125, 132, 131, 138, 137, 144, 143, 150, 149, 156, 155, 162, 161, 168, 167, 174, 173, 180, 179, 186, 185, 192, 191, 198, 197, 204, 203, 819, 818,
284, 283, 278, 277, 272, 271, 266, 265, 260, 259, 254, 253, 248, 247, 242, 241, 236, 235, 230, 229, 224, 223, 218, 217, 212, 211, 206, 205, 820, 0,
286, 285, 280, 279, 274, 273, 268, 267, 262, 261, 256, 255, 250, 249, 244, 243, 238, 237, 232, 231, 226, 225, 220, 219, 214, 213, 208, 207, 822, 821,
288, 287, 282, 281, 276, 275, 270, 269, 264, 263, 258, 257, 252, 251, 246, 245, 240, 239, 234, 233, 228, 227, 222, 221, 216, 215, 210, 209, 823, 0,
290, 289, 296, 295, 302, 301, 308, 307, 314, 313, 320, 319, 326, 325, 332, 331, 338, 337, 344, 343, 350, 349, 356, 355, 362, 361, 368, 367, 825, 824,
292, 291, 298, 297, 304, 303, 310, 309, 316, 315, 322, 321, 328, 327, 334, 333, 340, 339, 346, 345, 352, 351, 358, 357, 364, 363, 370, 369, 826, 0,
294, 293, 300, 299, 306, 305, 312, 311, 318, 317, 324, 323, 330, 329, 336, 335, 342, 341, 348, 347, 354, 353, 360, 359, 366, 365, 372, 371, 828, 827,
410, 409, 404, 403, 398, 397, 392, 391, 80, 79, 0, 0, 14, 13, 38, 37, 3, 0, 45, 44, 110, 109, 386, 385, 380, 379, 374, 373, 829, 0,
412, 411, 406, 405, 400, 399, 394, 393, 82, 81, 41, 0, 16, 15, 40, 39, 4, 0, 0, 46, 112, 111, 388, 387, 382, 381, 376, 375, 831, 830,
414, 413, 408, 407, 402, 401, 396, 395, 84, 83, 42, 0, 0, 0, 0, 0, 6, 5, 48, 47, 114, 113, 390, 389, 384, 383, 378, 377, 832, 0,
416, 415, 422, 421, 428, 427, 104, 103, 56, 55, 17, 0, 0, 0, 0, 0, 0, 0, 21, 20, 86, 85, 434, 433, 440, 439, 446, 445, 834, 833,
418, 417, 424, 423, 430, 429, 106, 105, 58, 57, 0, 0, 0, 0, 0, 0, 0, 0, 23, 22, 88, 87, 436, 435, 442, 441, 448, 447, 835, 0,
420, 419, 426, 425, 432, 431, 108, 107, 60, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 90, 89, 438, 437, 444, 443, 450, 449, 837, 836,
482, 481, 476, 475, 470, 469, 49, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 54, 53, 464, 463, 458, 457, 452, 451, 838, 0,
484, 483, 478, 477, 472, 471, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 466, 465, 460, 459, 454, 453, 840, 839,
486, 485, 480, 479, 474, 473, 52, 51, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 43, 468, 467, 462, 461, 456, 455, 841, 0,
488, 487, 494, 493, 500, 499, 98, 97, 62, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 92, 91, 506, 505, 512, 511, 518, 517, 843, 842,
490, 489, 496, 495, 502, 501, 100, 99, 64, 63, 0, 0, 0, 0, 0, 0, 0, 0, 29, 28, 94, 93, 508, 507, 514, 513, 520, 519, 844, 0,
492, 491, 498, 497, 504, 503, 102, 101, 66, 65, 18, 0, 0, 0, 0, 0, 0, 0, 19, 30, 96, 95, 510, 509, 516, 515, 522, 521, 846, 845,
560, 559, 554, 553, 548, 547, 542, 541, 74, 73, 33, 0, 0, 0, 0, 0, 0, 11, 68, 67, 116, 115, 536, 535, 530, 529, 524, 523, 847, 0,
562, 561, 556, 555, 550, 549, 544, 543, 76, 75, 0, 0, 8, 7, 36, 35, 12, 0, 70, 69, 118, 117, 538, 537, 532, 531, 526, 525, 849, 848,
564, 563, 558, 557, 552, 551, 546, 545, 78, 77, 0, 34, 10, 9, 26, 25, 0, 0, 72, 71, 120, 119, 540, 539, 534, 533, 528, 527, 850, 0,
566, 565, 572, 571, 578, 577, 584, 583, 590, 589, 596, 595, 602, 601, 608, 607, 614, 613, 620, 619, 626, 625, 632, 631, 638, 637, 644, 643, 852, 851,
568, 567, 574, 573, 580, 579, 586, 585, 592, 591, 598, 597, 604, 603, 610, 609, 616, 615, 622, 621, 628, 627, 634, 633, 640, 639, 646, 645, 853, 0,
570, 569, 576, 575, 582, 581, 588, 587, 594, 593, 600, 599, 606, 605, 612, 611, 618, 617, 624, 623, 630, 629, 636, 635, 642, 641, 648, 647, 855, 854,
728, 727, 722, 721, 716, 715, 710, 709, 704, 703, 698, 697, 692, 691, 686, 685, 680, 679, 674, 673, 668, 667, 662, 661, 656, 655, 650, 649, 856, 0,
730, 729, 724, 723, 718, 717, 712, 711, 706, 705, 700, 699, 694, 693, 688, 687, 682, 681, 676, 675, 670, 669, 664, 663, 658, 657, 652, 651, 858, 857,
732, 731, 726, 725, 720, 719, 714, 713, 708, 707, 702, 701, 696, 695, 690, 689, 684, 683, 678, 677, 672, 671, 666, 665, 660, 659, 654, 653, 859, 0,
734, 733, 740, 739, 746, 745, 752, 751, 758, 757, 764, 763, 770, 769, 776, 775, 782, 781, 788, 787, 794, 793, 800, 799, 806, 805, 812, 811, 861, 860,
736, 735, 742, 741, 748, 747, 754, 753, 760, 759, 766, 765, 772, 771, 778, 777, 784, 783, 790, 789, 796, 795, 802, 801, 808, 807, 814, 813, 862, 0,
738, 737, 744, 743, 750, 749, 756, 755, 762, 761, 768, 767, 774, 773, 780, 779, 786, 785, 792, 791, 798, 797, 804, 803, 810, 809, 816, 815, 864, 863
};
int maxiCodeSet[256] = { /* from Appendix A - ASCII character to Code Set (e.g. 2 = Set B) */
/* set 0 refers to special characters that fit into more than one set (e.g. GS) */
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 0, 2, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2,
2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 4, 5, 5, 5, 5, 5, 5, 4, 5, 3, 4, 3, 5, 5, 4, 4, 3, 3, 3,
4, 3, 5, 4, 4, 3, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
};
int maxiSymbolChar[256] = { /* from Appendix A - ASCII character to symbol value */
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 30, 28, 29, 30, 35, 32, 53, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 37,
38, 39, 40, 41, 52, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 42, 43, 44, 45, 46, 0, 1, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 32, 54, 34, 35, 36, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 36,
37, 37, 38, 39, 40, 41, 42, 43, 38, 44, 37, 39, 38, 45, 46, 40, 41, 39, 40, 41,
42, 42, 47, 43, 44, 43, 44, 45, 45, 46, 47, 46, 0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 32,
33, 34, 35, 36, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 32, 33, 34, 35, 36
};

138
backend/maxipng.h Normal file
View file

@ -0,0 +1,138 @@
/* maxipng.h - Shapes for Maxicode output to PNG file */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* This file contains the pixel-by-pixel representation of maxicode glyphs
at a resolution of 12 pixels per millimeter. hexagon[] is taken directly
from ISO 16023 Annex J. bullseye[] was calculated by the Gimp */
#define SSET "0123456789ABCDEF"
static int hexagon[120] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static unsigned int bullseye_compressed[] = {
0,0,0,0,0,255,248,0,0,0,0,0,
0,0,0,0,31,255,255,192,0,0,0,0,
0,0,0,1,255,255,255,252,0,0,0,0,
0,0,0,7,255,255,255,255,0,0,0,0,
0,0,0,31,255,255,255,255,192,0,0,0,
0,0,0,127,255,255,255,255,240,0,0,0,
0,0,1,255,255,255,255,255,252,0,0,0,
0,0,7,255,255,255,255,255,255,0,0,0,
0,0,15,255,255,0,7,255,255,128,0,0,
0,0,63,255,240,0,0,127,255,224,0,0,
0,0,127,255,128,0,0,15,255,240,0,0,
0,0,255,252,0,0,0,1,255,248,0,0,
0,1,255,240,0,0,0,0,127,252,0,0,
0,3,255,224,0,0,0,0,63,254,0,0,
0,7,255,128,0,0,0,0,15,255,0,0,
0,15,255,0,0,0,0,0,7,255,128,0,
0,31,252,0,0,127,240,0,1,255,192,0,
0,63,248,0,7,255,255,0,0,255,224,0,
0,127,240,0,63,255,255,224,0,127,240,0,
0,127,224,0,255,255,255,248,0,63,240,0,
0,255,192,1,255,255,255,252,0,31,248,0,
1,255,128,7,255,255,255,255,0,15,252,0,
1,255,0,15,255,255,255,255,128,7,252,0,
3,255,0,63,255,255,255,255,224,7,254,0,
3,254,0,127,255,192,31,255,240,3,254,0,
7,252,0,255,252,0,1,255,248,1,255,0,
7,252,1,255,240,0,0,127,252,1,255,0,
15,248,1,255,192,0,0,31,252,0,255,128,
15,240,3,255,128,0,0,15,254,0,127,128,
31,240,7,255,0,0,0,7,255,0,127,192,
31,224,7,254,0,0,0,3,255,0,63,192,
63,224,15,252,0,0,0,1,255,128,63,224,
63,224,31,248,0,63,192,0,255,192,63,224,
63,192,31,240,0,255,240,0,127,192,31,224,
63,192,63,224,3,255,252,0,63,224,31,224,
127,192,63,224,7,255,254,0,63,224,31,240,
127,128,63,192,15,255,255,0,31,224,15,240,
127,128,127,192,31,255,255,128,31,240,15,240,
127,128,127,128,63,255,255,192,15,240,15,240,
127,128,127,128,63,255,255,192,15,240,15,240,
255,0,127,128,127,240,255,224,15,240,7,240,
255,0,255,128,127,192,63,224,15,248,7,240,
255,0,255,0,255,128,31,240,7,248,7,240,
255,0,255,0,255,128,31,240,7,248,7,240,
255,0,255,0,255,0,15,240,7,248,7,240,
255,0,255,0,255,0,15,240,7,248,7,240,
255,0,255,0,255,0,15,240,7,248,7,240,
255,0,255,0,255,0,15,240,7,248,7,240,
255,0,255,0,255,128,31,240,7,248,7,240,
255,0,255,0,255,128,31,240,7,248,7,240,
255,0,255,0,127,192,63,224,7,248,7,240,
255,0,255,128,127,240,255,224,15,248,7,240,
255,0,127,128,63,255,255,192,15,240,7,240,
127,128,127,128,63,255,255,192,15,240,15,240,
127,128,127,128,31,255,255,128,15,240,15,240,
127,128,127,192,15,255,255,0,31,240,15,240,
127,128,63,192,7,255,254,0,31,224,15,240,
127,192,63,224,3,255,252,0,63,224,31,240,
63,192,63,224,0,255,240,0,63,224,31,224,
63,192,31,240,0,63,192,0,127,192,31,224,
63,224,31,248,0,0,0,0,255,192,63,224,
63,224,15,252,0,0,0,1,255,128,63,224,
31,224,7,254,0,0,0,3,255,0,63,192,
31,240,7,255,0,0,0,7,255,0,127,192,
15,240,3,255,128,0,0,15,254,0,127,128,
15,248,1,255,192,0,0,31,252,0,255,128,
7,252,1,255,240,0,0,127,252,1,255,0,
7,252,0,255,252,0,1,255,248,1,255,0,
3,254,0,127,255,192,31,255,240,3,254,0,
3,255,0,63,255,255,255,255,224,7,254,0,
1,255,0,15,255,255,255,255,128,7,252,0,
1,255,128,7,255,255,255,255,0,15,252,0,
0,255,192,1,255,255,255,252,0,31,248,0,
0,127,224,0,255,255,255,248,0,63,240,0,
0,127,240,0,63,255,255,224,0,127,240,0,
0,63,248,0,7,255,255,0,0,255,224,0,
0,31,252,0,0,127,240,0,1,255,192,0,
0,15,255,0,0,0,0,0,7,255,128,0,
0,7,255,128,0,0,0,0,15,255,0,0,
0,3,255,224,0,0,0,0,63,254,0,0,
0,1,255,240,0,0,0,0,127,252,0,0,
0,0,255,252,0,0,0,1,255,248,0,0,
0,0,127,255,128,0,0,15,255,240,0,0,
0,0,63,255,240,0,0,127,255,224,0,0,
0,0,15,255,255,0,7,255,255,128,0,0,
0,0,7,255,255,255,255,255,255,0,0,0,
0,0,1,255,255,255,255,255,252,0,0,0,
0,0,0,127,255,255,255,255,240,0,0,0,
0,0,0,31,255,255,255,255,192,0,0,0,
0,0,0,7,255,255,255,255,0,0,0,0,
0,0,0,1,255,255,255,252,0,0,0,0,
0,0,0,0,31,255,255,192,0,0,0,0,
0,0,0,0,0,255,248,0,0,0,0,0
};

308
backend/medical.c Normal file
View file

@ -0,0 +1,308 @@
/* medical.c - Handles 1 track and 2 track pharmacode and Codabar */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "common.h"
extern int c39(struct zint_symbol *symbol, unsigned char source[], int length);
/* Codabar table checked against EN 798:1995 */
#define CALCIUM "0123456789-$:/.+ABCD"
static char *CodaTable[20] = {"11111221", "11112211", "11121121", "22111111", "11211211", "21111211",
"12111121", "12112111", "12211111", "21121111", "11122111", "11221111", "21112121", "21211121",
"21212111", "11212121", "11221211", "12121121", "11121221", "11122211"};
int pharma_one(struct zint_symbol *symbol, unsigned char source[], int length)
{
/* "Pharmacode can represent only a single integer from 3 to 131070. Unlike other
commonly used one-dimensional barcode schemes, pharmacode does not store the data in a
form corresponding to the human-readable digits; the number is encoded in binary, rather
than decimal. Pharmacode is read from right to left: with n as the bar position starting
at 0 on the right, each narrow bar adds 2n to the value and each wide bar adds 2(2^n).
The minimum barcode is 2 bars and the maximum 16, so the smallest number that could
be encoded is 3 (2 narrow bars) and the biggest is 131070 (16 wide bars)."
- http://en.wikipedia.org/wiki/Pharmacode */
/* This code uses the One Track Pharamacode calculating algorithm as recommended by
the specification at http://www.laetus.com/laetus.php?request=file&id=69 */
unsigned long int tester;
int counter, error_number, h;
char inter[18] = { 0 }; /* 131070 -> 17 bits */
char dest[64]; /* 17 * 2 + 1 */
error_number = 0;
if(length > 6) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
tester = atoi((char*)source);
if((tester < 3) || (tester > 131070)) {
strcpy(symbol->errtxt, "Data out of range");
return ERROR_INVALID_DATA;
}
do
{
if(tester % 2 == 0) {
concat(inter, "W");
tester = (tester - 2) / 2;
} else {
concat(inter, "N");
tester = (tester - 1) / 2;
}
}
while(tester != 0);
h = strlen(inter) - 1;
*dest = '\0';
for(counter = h; counter >= 0; counter--) {
if(inter[counter] == 'W') {
concat(dest, "32");
} else {
concat(dest, "12");
}
}
expand(symbol, dest);
return error_number;
}
int pharma_two_calc(struct zint_symbol *symbol, unsigned char source[], char dest[])
{
/* This code uses the Two Track Pharamacode defined in the document at
http://www.laetus.com/laetus.php?request=file&id=69 and using a modified
algorithm from the One Track system. This standard accepts integet values
from 4 to 64570080. */
unsigned long int tester;
int counter, h;
char inter[17];
int error_number;
tester = atoi((char*)source);
if((tester < 4) || (tester > 64570080))
{
strcpy(symbol->errtxt, "Data out of range");
return ERROR_INVALID_DATA;
}
error_number = 0;
strcpy(inter, "");
do
{
switch(tester%3) {
case 0:
concat(inter, "3");
tester = (tester - 3) / 3;
break;
case 1:
concat(inter, "1");
tester = (tester - 1) / 3;
break;
case 2:
concat(inter, "2");
tester = (tester - 2) / 3;
break;
}
}
while(tester != 0);
h = strlen(inter) - 1;
for(counter = h; counter >= 0; counter--)
{
dest[h - counter] = inter[counter];
}
dest[h + 1] = '\0';
return error_number;
}
int pharma_two(struct zint_symbol *symbol, unsigned char source[], int length)
{
/* Draws the patterns for two track pharmacode */
char height_pattern[200];
unsigned int loopey, h;
int writer;
int error_number = 0;
strcpy(height_pattern, "");
if(length > 8) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
error_number = pharma_two_calc(symbol, source, height_pattern);
if(error_number != 0) {
return error_number;
}
writer = 0;
h = strlen(height_pattern);
for(loopey = 0; loopey < h; loopey++)
{
if((height_pattern[loopey] == '2') || (height_pattern[loopey] == '3'))
{
set_module(symbol, 0, writer);
}
if((height_pattern[loopey] == '1') || (height_pattern[loopey] == '3'))
{
set_module(symbol, 1, writer);
}
writer += 2;
}
symbol->rows = 2;
symbol->width = writer - 1;
return error_number;
}
int codabar(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* The Codabar system consisting of simple substitution */
int i, error_number;
char dest[512];
error_number = 0;
strcpy(dest, "");
if(length > 60) { /* No stack smashing please */
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
to_upper(source);
error_number = is_sane(CALCIUM, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
/* Codabar must begin and end with the characters A, B, C or D */
if((source[0] != 'A') && (source[0] != 'B') && (source[0] != 'C') && (source[0] != 'D'))
{
strcpy(symbol->errtxt, "Invalid characters in data");
return ERROR_INVALID_DATA;
}
if((source[length - 1] != 'A') && (source[length - 1] != 'B') &&
(source[length - 1] != 'C') && (source[length - 1] != 'D'))
{
strcpy(symbol->errtxt, "Invalid characters in data");
return ERROR_INVALID_DATA;
}
for(i = 0; i < length; i++)
{
lookup(CALCIUM, CodaTable, source[i], dest);
}
expand(symbol, dest);
ustrcpy(symbol->text, source);
return error_number;
}
int code32(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Italian Pharmacode */
int i, zeroes, error_number, checksum, checkpart, checkdigit;
char localstr[10], risultante[7];
long int pharmacode, remainder, devisor;
int codeword[6];
char tabella[34];
/* Validate the input */
if(length > 8) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
/* Add leading zeros as required */
zeroes = 8 - length;
memset(localstr, '0', zeroes);
strcpy(localstr + zeroes, (char*)source);
/* Calculate the check digit */
checksum = 0;
checkpart = 0;
for(i = 0; i < 4; i++) {
checkpart = ctoi(localstr[i * 2]);
checksum += checkpart;
checkpart = 2 * (ctoi(localstr[(i * 2) + 1]));
if(checkpart >= 10) {
checksum += (checkpart - 10) + 1;
} else {
checksum += checkpart;
}
}
/* Add check digit to data string */
checkdigit = checksum % 10;
localstr[8] = itoc(checkdigit);
localstr[9] = '\0';
/* Convert string into an integer value */
pharmacode = atoi(localstr);
/* Convert from decimal to base-32 */
devisor = 33554432;
for(i = 5; i >= 0; i--) {
codeword[i] = pharmacode / devisor;
remainder = pharmacode % devisor;
pharmacode = remainder;
devisor /= 32;
}
/* Look up values in 'Tabella di conversione' */
strcpy(tabella, "0123456789BCDFGHJKLMNPQRSTUVWXYZ");
for(i = 5; i >= 0; i--) {
risultante[5 - i] = tabella[codeword[i]];
}
risultante[6] = '\0';
/* Plot the barcode using Code 39 */
error_number = c39(symbol, (unsigned char*)risultante, strlen(risultante));
if(error_number != 0) { return error_number; }
/* Override the normal text output with the Pharmacode number */
ustrcpy(symbol->text, (unsigned char*)"A");
uconcat(symbol->text, (unsigned char*)localstr);
return error_number;
}

234
backend/ms_stdint.h Normal file
View file

@ -0,0 +1,234 @@
// ISO C9x compliant stdint.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
//
// Copyright (c) 2006-2008 Alexander Chemeris
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The name of the author may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////
/* @(#) $Id: ms_stdint.h,v 1.1 2009/09/19 08:16:21 hooper114 Exp $ */
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef _MSC_STDINT_H_ // [
#define _MSC_STDINT_H_
#if _MSC_VER > 1000
#pragma once
#endif
#include <limits.h>
// For Visual Studio 6 in C++ mode wrap <wchar.h> include with 'extern "C++" {}'
// or compiler give many errors like this:
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
#if (_MSC_VER < 1300) && defined(__cplusplus)
extern "C++" {
#endif
# include <wchar.h>
#if (_MSC_VER < 1300) && defined(__cplusplus)
}
#endif
// Define _W64 macros to mark types changing their size, like intptr_t.
#ifndef _W64
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
# define _W64 __w64
# else
# define _W64
# endif
#endif
// 7.18.1 Integer types
// 7.18.1.1 Exact-width integer types
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
// 7.18.1.2 Minimum-width integer types
typedef int8_t int_least8_t;
typedef int16_t int_least16_t;
typedef int32_t int_least32_t;
typedef int64_t int_least64_t;
typedef uint8_t uint_least8_t;
typedef uint16_t uint_least16_t;
typedef uint32_t uint_least32_t;
typedef uint64_t uint_least64_t;
// 7.18.1.3 Fastest minimum-width integer types
typedef int8_t int_fast8_t;
typedef int16_t int_fast16_t;
typedef int32_t int_fast32_t;
typedef int64_t int_fast64_t;
typedef uint8_t uint_fast8_t;
typedef uint16_t uint_fast16_t;
typedef uint32_t uint_fast32_t;
typedef uint64_t uint_fast64_t;
// 7.18.1.4 Integer types capable of holding object pointers
#ifdef _WIN64 // [
typedef __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
#else // _WIN64 ][
typedef _W64 int intptr_t;
typedef _W64 unsigned int uintptr_t;
#endif // _WIN64 ]
// 7.18.1.5 Greatest-width integer types
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
// 7.18.2 Limits of specified-width integer types
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
// 7.18.2.1 Limits of exact-width integer types
#define INT8_MIN ((int8_t)_I8_MIN)
#define INT8_MAX _I8_MAX
#define INT16_MIN ((int16_t)_I16_MIN)
#define INT16_MAX _I16_MAX
#define INT32_MIN ((int32_t)_I32_MIN)
#define INT32_MAX _I32_MAX
#define INT64_MIN ((int64_t)_I64_MIN)
#define INT64_MAX _I64_MAX
#define UINT8_MAX _UI8_MAX
#define UINT16_MAX _UI16_MAX
#define UINT32_MAX _UI32_MAX
#define UINT64_MAX _UI64_MAX
// 7.18.2.2 Limits of minimum-width integer types
#define INT_LEAST8_MIN INT8_MIN
#define INT_LEAST8_MAX INT8_MAX
#define INT_LEAST16_MIN INT16_MIN
#define INT_LEAST16_MAX INT16_MAX
#define INT_LEAST32_MIN INT32_MIN
#define INT_LEAST32_MAX INT32_MAX
#define INT_LEAST64_MIN INT64_MIN
#define INT_LEAST64_MAX INT64_MAX
#define UINT_LEAST8_MAX UINT8_MAX
#define UINT_LEAST16_MAX UINT16_MAX
#define UINT_LEAST32_MAX UINT32_MAX
#define UINT_LEAST64_MAX UINT64_MAX
// 7.18.2.3 Limits of fastest minimum-width integer types
#define INT_FAST8_MIN INT8_MIN
#define INT_FAST8_MAX INT8_MAX
#define INT_FAST16_MIN INT16_MIN
#define INT_FAST16_MAX INT16_MAX
#define INT_FAST32_MIN INT32_MIN
#define INT_FAST32_MAX INT32_MAX
#define INT_FAST64_MIN INT64_MIN
#define INT_FAST64_MAX INT64_MAX
#define UINT_FAST8_MAX UINT8_MAX
#define UINT_FAST16_MAX UINT16_MAX
#define UINT_FAST32_MAX UINT32_MAX
#define UINT_FAST64_MAX UINT64_MAX
// 7.18.2.4 Limits of integer types capable of holding object pointers
#ifdef _WIN64 // [
# define INTPTR_MIN INT64_MIN
# define INTPTR_MAX INT64_MAX
# define UINTPTR_MAX UINT64_MAX
#else // _WIN64 ][
# define INTPTR_MIN INT32_MIN
# define INTPTR_MAX INT32_MAX
# define UINTPTR_MAX UINT32_MAX
#endif // _WIN64 ]
// 7.18.2.5 Limits of greatest-width integer types
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX
// 7.18.3 Limits of other integer types
#ifdef _WIN64 // [
# define PTRDIFF_MIN _I64_MIN
# define PTRDIFF_MAX _I64_MAX
#else // _WIN64 ][
# define PTRDIFF_MIN _I32_MIN
# define PTRDIFF_MAX _I32_MAX
#endif // _WIN64 ]
#define SIG_ATOMIC_MIN INT_MIN
#define SIG_ATOMIC_MAX INT_MAX
#ifndef SIZE_MAX // [
# ifdef _WIN64 // [
# define SIZE_MAX _UI64_MAX
# else // _WIN64 ][
# define SIZE_MAX _UI32_MAX
# endif // _WIN64 ]
#endif // SIZE_MAX ]
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
#ifndef WCHAR_MIN // [
# define WCHAR_MIN 0
#endif // WCHAR_MIN ]
#ifndef WCHAR_MAX // [
# define WCHAR_MAX _UI16_MAX
#endif // WCHAR_MAX ]
#define WINT_MIN 0
#define WINT_MAX _UI16_MAX
#endif // __STDC_LIMIT_MACROS ]
// 7.18.4 Limits of other integer types
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
// 7.18.4.1 Macros for minimum-width integer constants
#define INT8_C(val) val##i8
#define INT16_C(val) val##i16
#define INT32_C(val) val##i32
#define INT64_C(val) val##i64
#define UINT8_C(val) val##ui8
#define UINT16_C(val) val##ui16
#define UINT32_C(val) val##ui32
#define UINT64_C(val) val##ui64
// 7.18.4.2 Macros for greatest-width integer constants
#define INTMAX_C INT64_C
#define UINTMAX_C UINT64_C
#endif // __STDC_CONSTANT_MACROS ]
#endif // _MSC_STDINT_H_ ]

1083
backend/pdf417.c Normal file

File diff suppressed because it is too large Load diff

438
backend/pdf417.h Normal file
View file

@ -0,0 +1,438 @@
/* pdf417.h - PDF417 tables and coefficients */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
Portions Copyright (C) 2004 Grandzebu
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* this file contains the character table, the pre-calculated coefficients and the
codeword patterns taken from lines 416 to 454 of pdf417.frm */
#define TRUE 1
#define FALSE 0
#define TEX 900
#define BYT 901
#define NUM 902
#define BRSET "ABCDEFabcdefghijklmnopqrstuvwxyz*+-"
/* PDF417 error correction coefficients from Grand Zebu */
static int coefrs[1022] = {
/* k = 2 */
27, 917,
/* k = 4 */
522, 568, 723, 809,
/* k = 8 */
237, 308, 436, 284, 646, 653, 428, 379,
/* k = 16 */
274, 562, 232, 755, 599, 524, 801, 132, 295, 116, 442, 428, 295, 42, 176, 65,
/* k = 32 */
361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517,
273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410,
/* k = 64 */
539, 422, 6, 93, 862, 771, 453, 106, 610, 287, 107, 505, 733, 877, 381, 612,
723, 476, 462, 172, 430, 609, 858, 822, 543, 376, 511, 400, 672, 762, 283, 184,
440, 35, 519, 31, 460, 594, 225, 535, 517, 352, 605, 158, 651, 201, 488, 502,
648, 733, 717, 83, 404, 97, 280, 771, 840, 629, 4, 381, 843, 623, 264, 543,
/* k = 128 */
521, 310, 864, 547, 858, 580, 296, 379, 53, 779, 897, 444, 400, 925, 749, 415,
822, 93, 217, 208, 928, 244, 583, 620, 246, 148, 447, 631, 292, 908, 490, 704,
516, 258, 457, 907, 594, 723, 674, 292, 272, 96, 684, 432, 686, 606, 860, 569,
193, 219, 129, 186, 236, 287, 192, 775, 278, 173, 40, 379, 712, 463, 646, 776,
171, 491, 297, 763, 156, 732, 95, 270, 447, 90, 507, 48, 228, 821, 808, 898,
784, 663, 627, 378, 382, 262, 380, 602, 754, 336, 89, 614, 87, 432, 670, 616,
157, 374, 242, 726, 600, 269, 375, 898, 845, 454, 354, 130, 814, 587, 804, 34,
211, 330, 539, 297, 827, 865, 37, 517, 834, 315, 550, 86, 801, 4, 108, 539,
/* k = 256 */
524, 894, 75, 766, 882, 857, 74, 204, 82, 586, 708, 250, 905, 786, 138, 720,
858, 194, 311, 913, 275, 190, 375, 850, 438, 733, 194, 280, 201, 280, 828, 757,
710, 814, 919, 89, 68, 569, 11, 204, 796, 605, 540, 913, 801, 700, 799, 137,
439, 418, 592, 668, 353, 859, 370, 694, 325, 240, 216, 257, 284, 549, 209, 884,
315, 70, 329, 793, 490, 274, 877, 162, 749, 812, 684, 461, 334, 376, 849, 521,
307, 291, 803, 712, 19, 358, 399, 908, 103, 511, 51, 8, 517, 225, 289, 470,
637, 731, 66, 255, 917, 269, 463, 830, 730, 433, 848, 585, 136, 538, 906, 90,
2, 290, 743, 199, 655, 903, 329, 49, 802, 580, 355, 588, 188, 462, 10, 134,
628, 320, 479, 130, 739, 71, 263, 318, 374, 601, 192, 605, 142, 673, 687, 234,
722, 384, 177, 752, 607, 640, 455, 193, 689, 707, 805, 641, 48, 60, 732, 621,
895, 544, 261, 852, 655, 309, 697, 755, 756, 60, 231, 773, 434, 421, 726, 528,
503, 118, 49, 795, 32, 144, 500, 238, 836, 394, 280, 566, 319, 9, 647, 550,
73, 914, 342, 126, 32, 681, 331, 792, 620, 60, 609, 441, 180, 791, 893, 754,
605, 383, 228, 749, 760, 213, 54, 297, 134, 54, 834, 299, 922, 191, 910, 532,
609, 829, 189, 20, 167, 29, 872, 449, 83, 402, 41, 656, 505, 579, 481, 173,
404, 251, 688, 95, 497, 555, 642, 543, 307, 159, 924, 558, 648, 55, 497, 10,
/* k = 512 */
352, 77, 373, 504, 35, 599, 428, 207, 409, 574, 118, 498, 285, 380, 350, 492,
197, 265, 920, 155, 914, 299, 229, 643, 294, 871, 306, 88, 87, 193, 352, 781,
846, 75, 327, 520, 435, 543, 203, 666, 249, 346, 781, 621, 640, 268, 794, 534,
539, 781, 408, 390, 644, 102, 476, 499, 290, 632, 545, 37, 858, 916, 552, 41,
542, 289, 122, 272, 383, 800, 485, 98, 752, 472, 761, 107, 784, 860, 658, 741,
290, 204, 681, 407, 855, 85, 99, 62, 482, 180, 20, 297, 451, 593, 913, 142,
808, 684, 287, 536, 561, 76, 653, 899, 729, 567, 744, 390, 513, 192, 516, 258,
240, 518, 794, 395, 768, 848, 51, 610, 384, 168, 190, 826, 328, 596, 786, 303,
570, 381, 415, 641, 156, 237, 151, 429, 531, 207, 676, 710, 89, 168, 304, 402,
40, 708, 575, 162, 864, 229, 65, 861, 841, 512, 164, 477, 221, 92, 358, 785,
288, 357, 850, 836, 827, 736, 707, 94, 8, 494, 114, 521, 2, 499, 851, 543,
152, 729, 771, 95, 248, 361, 578, 323, 856, 797, 289, 51, 684, 466, 533, 820,
669, 45, 902, 452, 167, 342, 244, 173, 35, 463, 651, 51, 699, 591, 452, 578,
37, 124, 298, 332, 552, 43, 427, 119, 662, 777, 475, 850, 764, 364, 578, 911,
283, 711, 472, 420, 245, 288, 594, 394, 511, 327, 589, 777, 699, 688, 43, 408,
842, 383, 721, 521, 560, 644, 714, 559, 62, 145, 873, 663, 713, 159, 672, 729,
624, 59, 193, 417, 158, 209, 563, 564, 343, 693, 109, 608, 563, 365, 181, 772,
677, 310, 248, 353, 708, 410, 579, 870, 617, 841, 632, 860, 289, 536, 35, 777,
618, 586, 424, 833, 77, 597, 346, 269, 757, 632, 695, 751, 331, 247, 184, 45,
787, 680, 18, 66, 407, 369, 54, 492, 228, 613, 830, 922, 437, 519, 644, 905,
789, 420, 305, 441, 207, 300, 892, 827, 141, 537, 381, 662, 513, 56, 252, 341,
242, 797, 838, 837, 720, 224, 307, 631, 61, 87, 560, 310, 756, 665, 397, 808,
851, 309, 473, 795, 378, 31, 647, 915, 459, 806, 590, 731, 425, 216, 548, 249,
321, 881, 699, 535, 673, 782, 210, 815, 905, 303, 843, 922, 281, 73, 469, 791,
660, 162, 498, 308, 155, 422, 907, 817, 187, 62, 16, 425, 535, 336, 286, 437,
375, 273, 610, 296, 183, 923, 116, 667, 751, 353, 62, 366, 691, 379, 687, 842,
37, 357, 720, 742, 330, 5, 39, 923, 311, 424, 242, 749, 321, 54, 669, 316,
342, 299, 534, 105, 667, 488, 640, 672, 576, 540, 316, 486, 721, 610, 46, 656,
447, 171, 616, 464, 190, 531, 297, 321, 762, 752, 533, 175, 134, 14, 381, 433,
717, 45, 111, 20, 596, 284, 736, 138, 646, 411, 877, 669, 141, 919, 45, 780,
407, 164, 332, 899, 165, 726, 600, 325, 498, 655, 357, 752, 768, 223, 849, 647,
63, 310, 863, 251, 366, 304, 282, 738, 675, 410, 389, 244, 31, 121, 303, 263 };
static char *codagemc[2787] = { "urA", "xfs", "ypy", "unk", "xdw", "yoz", "pDA", "uls", "pBk", "eBA",
"pAs", "eAk", "prA", "uvs", "xhy", "pnk", "utw", "xgz", "fDA", "pls", "fBk", "frA", "pvs",
"uxy", "fnk", "ptw", "uwz", "fls", "psy", "fvs", "pxy", "ftw", "pwz", "fxy", "yrx", "ufk",
"xFw", "ymz", "onA", "uds", "xEy", "olk", "ucw", "dBA", "oks", "uci", "dAk", "okg", "dAc",
"ovk", "uhw", "xaz", "dnA", "ots", "ugy", "dlk", "osw", "ugj", "dks", "osi", "dvk", "oxw",
"uiz", "dts", "owy", "dsw", "owj", "dxw", "oyz", "dwy", "dwj", "ofA", "uFs", "xCy", "odk",
"uEw", "xCj", "clA", "ocs", "uEi", "ckk", "ocg", "ckc", "ckE", "cvA", "ohs", "uay", "ctk",
"ogw", "uaj", "css", "ogi", "csg", "csa", "cxs", "oiy", "cww", "oij", "cwi", "cyy", "oFk",
"uCw", "xBj", "cdA", "oEs", "uCi", "cck", "oEg", "uCb", "ccc", "oEa", "ccE", "oED", "chk",
"oaw", "uDj", "cgs", "oai", "cgg", "oab", "cga", "cgD", "obj", "cib", "cFA", "oCs", "uBi",
"cEk", "oCg", "uBb", "cEc", "oCa", "cEE", "oCD", "cEC", "cas", "cag", "caa", "cCk", "uAr",
"oBa", "oBD", "cCB", "tfk", "wpw", "yez", "mnA", "tds", "woy", "mlk", "tcw", "woj", "FBA",
"mks", "FAk", "mvk", "thw", "wqz", "FnA", "mts", "tgy", "Flk", "msw", "Fks", "Fkg", "Fvk",
"mxw", "tiz", "Fts", "mwy", "Fsw", "Fsi", "Fxw", "myz", "Fwy", "Fyz", "vfA", "xps", "yuy",
"vdk", "xow", "yuj", "qlA", "vcs", "xoi", "qkk", "vcg", "xob", "qkc", "vca", "mfA", "tFs",
"wmy", "qvA", "mdk", "tEw", "wmj", "qtk", "vgw", "xqj", "hlA", "Ekk", "mcg", "tEb", "hkk",
"qsg", "hkc", "EvA", "mhs", "tay", "hvA", "Etk", "mgw", "taj", "htk", "qww", "vij", "hss",
"Esg", "hsg", "Exs", "miy", "hxs", "Eww", "mij", "hww", "qyj", "hwi", "Eyy", "hyy", "Eyj",
"hyj", "vFk", "xmw", "ytj", "qdA", "vEs", "xmi", "qck", "vEg", "xmb", "qcc", "vEa", "qcE",
"qcC", "mFk", "tCw", "wlj", "qhk", "mEs", "tCi", "gtA", "Eck", "vai", "tCb", "gsk", "Ecc",
"mEa", "gsc", "qga", "mED", "EcC", "Ehk", "maw", "tDj", "gxk", "Egs", "mai", "gws", "qii",
"mab", "gwg", "Ega", "EgD", "Eiw", "mbj", "gyw", "Eii", "gyi", "Eib", "gyb", "gzj", "qFA",
"vCs", "xli", "qEk", "vCg", "xlb", "qEc", "vCa", "qEE", "vCD", "qEC", "qEB", "EFA", "mCs",
"tBi", "ghA", "EEk", "mCg", "tBb", "ggk", "qag", "vDb", "ggc", "EEE", "mCD", "ggE", "qaD",
"ggC", "Eas", "mDi", "gis", "Eag", "mDb", "gig", "qbb", "gia", "EaD", "giD", "gji", "gjb",
"qCk", "vBg", "xkr", "qCc", "vBa", "qCE", "vBD", "qCC", "qCB", "ECk", "mBg", "tAr", "gak",
"ECc", "mBa", "gac", "qDa", "mBD", "gaE", "ECC", "gaC", "ECB", "EDg", "gbg", "gba", "gbD",
"vAq", "vAn", "qBB", "mAq", "EBE", "gDE", "gDC", "gDB", "lfA", "sps", "wey", "ldk", "sow",
"ClA", "lcs", "soi", "Ckk", "lcg", "Ckc", "CkE", "CvA", "lhs", "sqy", "Ctk", "lgw", "sqj",
"Css", "lgi", "Csg", "Csa", "Cxs", "liy", "Cww", "lij", "Cwi", "Cyy", "Cyj", "tpk", "wuw",
"yhj", "ndA", "tos", "wui", "nck", "tog", "wub", "ncc", "toa", "ncE", "toD", "lFk", "smw",
"wdj", "nhk", "lEs", "smi", "atA", "Cck", "tqi", "smb", "ask", "ngg", "lEa", "asc", "CcE",
"asE", "Chk", "law", "snj", "axk", "Cgs", "trj", "aws", "nii", "lab", "awg", "Cga", "awa",
"Ciw", "lbj", "ayw", "Cii", "ayi", "Cib", "Cjj", "azj", "vpA", "xus", "yxi", "vok", "xug",
"yxb", "voc", "xua", "voE", "xuD", "voC", "nFA", "tms", "wti", "rhA", "nEk", "xvi", "wtb",
"rgk", "vqg", "xvb", "rgc", "nEE", "tmD", "rgE", "vqD", "nEB", "CFA", "lCs", "sli", "ahA",
"CEk", "lCg", "slb", "ixA", "agk", "nag", "tnb", "iwk", "rig", "vrb", "lCD", "iwc", "agE",
"naD", "iwE", "CEB", "Cas", "lDi", "ais", "Cag", "lDb", "iys", "aig", "nbb", "iyg", "rjb",
"CaD", "aiD", "Cbi", "aji", "Cbb", "izi", "ajb", "vmk", "xtg", "ywr", "vmc", "xta", "vmE",
"xtD", "vmC", "vmB", "nCk", "tlg", "wsr", "rak", "nCc", "xtr", "rac", "vna", "tlD", "raE",
"nCC", "raC", "nCB", "raB", "CCk", "lBg", "skr", "aak", "CCc", "lBa", "iik", "aac", "nDa",
"lBD", "iic", "rba", "CCC", "iiE", "aaC", "CCB", "aaB", "CDg", "lBr", "abg", "CDa", "ijg",
"aba", "CDD", "ija", "abD", "CDr", "ijr", "vlc", "xsq", "vlE", "xsn", "vlC", "vlB", "nBc",
"tkq", "rDc", "nBE", "tkn", "rDE", "vln", "rDC", "nBB", "rDB", "CBc", "lAq", "aDc", "CBE",
"lAn", "ibc", "aDE", "nBn", "ibE", "rDn", "CBB", "ibC", "aDB", "ibB", "aDq", "ibq", "ibn",
"xsf", "vkl", "tkf", "nAm", "nAl", "CAo", "aBo", "iDo", "CAl", "aBl", "kpk", "BdA", "kos",
"Bck", "kog", "seb", "Bcc", "koa", "BcE", "koD", "Bhk", "kqw", "sfj", "Bgs", "kqi", "Bgg",
"kqb", "Bga", "BgD", "Biw", "krj", "Bii", "Bib", "Bjj", "lpA", "sus", "whi", "lok", "sug",
"loc", "sua", "loE", "suD", "loC", "BFA", "kms", "sdi", "DhA", "BEk", "svi", "sdb", "Dgk",
"lqg", "svb", "Dgc", "BEE", "kmD", "DgE", "lqD", "BEB", "Bas", "kni", "Dis", "Bag", "knb",
"Dig", "lrb", "Dia", "BaD", "Bbi", "Dji", "Bbb", "Djb", "tuk", "wxg", "yir", "tuc", "wxa",
"tuE", "wxD", "tuC", "tuB", "lmk", "stg", "nqk", "lmc", "sta", "nqc", "tva", "stD", "nqE",
"lmC", "nqC", "lmB", "nqB", "BCk", "klg", "Dak", "BCc", "str", "bik", "Dac", "lna", "klD",
"bic", "nra", "BCC", "biE", "DaC", "BCB", "DaB", "BDg", "klr", "Dbg", "BDa", "bjg", "Dba",
"BDD", "bja", "DbD", "BDr", "Dbr", "bjr", "xxc", "yyq", "xxE", "yyn", "xxC", "xxB", "ttc",
"wwq", "vvc", "xxq", "wwn", "vvE", "xxn", "vvC", "ttB", "vvB", "llc", "ssq", "nnc", "llE",
"ssn", "rrc", "nnE", "ttn", "rrE", "vvn", "llB", "rrC", "nnB", "rrB", "BBc", "kkq", "DDc",
"BBE", "kkn", "bbc", "DDE", "lln", "jjc", "bbE", "nnn", "BBB", "jjE", "rrn", "DDB", "jjC",
"BBq", "DDq", "BBn", "bbq", "DDn", "jjq", "bbn", "jjn", "xwo", "yyf", "xwm", "xwl", "tso",
"wwf", "vto", "xwv", "vtm", "tsl", "vtl", "lko", "ssf", "nlo", "lkm", "rno", "nlm", "lkl",
"rnm", "nll", "rnl", "BAo", "kkf", "DBo", "lkv", "bDo", "DBm", "BAl", "jbo", "bDm", "DBl",
"jbm", "bDl", "jbl", "DBv", "jbv", "xwd", "vsu", "vst", "nku", "rlu", "rlt", "DAu", "bBu",
"jDu", "jDt", "ApA", "Aok", "keg", "Aoc", "AoE", "AoC", "Aqs", "Aqg", "Aqa", "AqD", "Ari",
"Arb", "kuk", "kuc", "sha", "kuE", "shD", "kuC", "kuB", "Amk", "kdg", "Bqk", "kvg", "kda",
"Bqc", "kva", "BqE", "kvD", "BqC", "AmB", "BqB", "Ang", "kdr", "Brg", "kvr", "Bra", "AnD",
"BrD", "Anr", "Brr", "sxc", "sxE", "sxC", "sxB", "ktc", "lvc", "sxq", "sgn", "lvE", "sxn",
"lvC", "ktB", "lvB", "Alc", "Bnc", "AlE", "kcn", "Drc", "BnE", "AlC", "DrE", "BnC", "AlB",
"DrC", "BnB", "Alq", "Bnq", "Aln", "Drq", "Bnn", "Drn", "wyo", "wym", "wyl", "swo", "txo",
"wyv", "txm", "swl", "txl", "kso", "sgf", "lto", "swv", "nvo", "ltm", "ksl", "nvm", "ltl",
"nvl", "Ako", "kcf", "Blo", "ksv", "Dno", "Blm", "Akl", "bro", "Dnm", "Bll", "brm", "Dnl",
"Akv", "Blv", "Dnv", "brv", "yze", "yzd", "wye", "xyu", "wyd", "xyt", "swe", "twu", "swd",
"vxu", "twt", "vxt", "kse", "lsu", "ksd", "ntu", "lst", "rvu", "ypk", "zew", "xdA", "yos",
"zei", "xck", "yog", "zeb", "xcc", "yoa", "xcE", "yoD", "xcC", "xhk", "yqw", "zfj", "utA",
"xgs", "yqi", "usk", "xgg", "yqb", "usc", "xga", "usE", "xgD", "usC", "uxk", "xiw", "yrj",
"ptA", "uws", "xii", "psk", "uwg", "xib", "psc", "uwa", "psE", "uwD", "psC", "pxk", "uyw",
"xjj", "ftA", "pws", "uyi", "fsk", "pwg", "uyb", "fsc", "pwa", "fsE", "pwD", "fxk", "pyw",
"uzj", "fws", "pyi", "fwg", "pyb", "fwa", "fyw", "pzj", "fyi", "fyb", "xFA", "yms", "zdi",
"xEk", "ymg", "zdb", "xEc", "yma", "xEE", "ymD", "xEC", "xEB", "uhA", "xas", "yni", "ugk",
"xag", "ynb", "ugc", "xaa", "ugE", "xaD", "ugC", "ugB", "oxA", "uis", "xbi", "owk", "uig",
"xbb", "owc", "uia", "owE", "uiD", "owC", "owB", "dxA", "oys", "uji", "dwk", "oyg", "ujb",
"dwc", "oya", "dwE", "oyD", "dwC", "dys", "ozi", "dyg", "ozb", "dya", "dyD", "dzi", "dzb",
"xCk", "ylg", "zcr", "xCc", "yla", "xCE", "ylD", "xCC", "xCB", "uak", "xDg", "ylr", "uac",
"xDa", "uaE", "xDD", "uaC", "uaB", "oik", "ubg", "xDr", "oic", "uba", "oiE", "ubD", "oiC",
"oiB", "cyk", "ojg", "ubr", "cyc", "oja", "cyE", "ojD", "cyC", "cyB", "czg", "ojr", "cza",
"czD", "czr", "xBc", "ykq", "xBE", "ykn", "xBC", "xBB", "uDc", "xBq", "uDE", "xBn", "uDC",
"uDB", "obc", "uDq", "obE", "uDn", "obC", "obB", "cjc", "obq", "cjE", "obn", "cjC", "cjB",
"cjq", "cjn", "xAo", "ykf", "xAm", "xAl", "uBo", "xAv", "uBm", "uBl", "oDo", "uBv", "oDm",
"oDl", "cbo", "oDv", "cbm", "cbl", "xAe", "xAd", "uAu", "uAt", "oBu", "oBt", "wpA", "yes",
"zFi", "wok", "yeg", "zFb", "woc", "yea", "woE", "yeD", "woC", "woB", "thA", "wqs", "yfi",
"tgk", "wqg", "yfb", "tgc", "wqa", "tgE", "wqD", "tgC", "tgB", "mxA", "tis", "wri", "mwk",
"tig", "wrb", "mwc", "tia", "mwE", "tiD", "mwC", "mwB", "FxA", "mys", "tji", "Fwk", "myg",
"tjb", "Fwc", "mya", "FwE", "myD", "FwC", "Fys", "mzi", "Fyg", "mzb", "Fya", "FyD", "Fzi",
"Fzb", "yuk", "zhg", "hjs", "yuc", "zha", "hbw", "yuE", "zhD", "hDy", "yuC", "yuB", "wmk",
"ydg", "zEr", "xqk", "wmc", "zhr", "xqc", "yva", "ydD", "xqE", "wmC", "xqC", "wmB", "xqB",
"tak", "wng", "ydr", "vik", "tac", "wna", "vic", "xra", "wnD", "viE", "taC", "viC", "taB",
"viB", "mik", "tbg", "wnr", "qyk", "mic", "tba", "qyc", "vja", "tbD", "qyE", "miC", "qyC",
"miB", "qyB", "Eyk", "mjg", "tbr", "hyk", "Eyc", "mja", "hyc", "qza", "mjD", "hyE", "EyC",
"hyC", "EyB", "Ezg", "mjr", "hzg", "Eza", "hza", "EzD", "hzD", "Ezr", "ytc", "zgq", "grw",
"ytE", "zgn", "gny", "ytC", "glz", "ytB", "wlc", "ycq", "xnc", "wlE", "ycn", "xnE", "ytn",
"xnC", "wlB", "xnB", "tDc", "wlq", "vbc", "tDE", "wln", "vbE", "xnn", "vbC", "tDB", "vbB",
"mbc", "tDq", "qjc", "mbE", "tDn", "qjE", "vbn", "qjC", "mbB", "qjB", "Ejc", "mbq", "gzc",
"EjE", "mbn", "gzE", "qjn", "gzC", "EjB", "gzB", "Ejq", "gzq", "Ejn", "gzn", "yso", "zgf",
"gfy", "ysm", "gdz", "ysl", "wko", "ycf", "xlo", "ysv", "xlm", "wkl", "xll", "tBo", "wkv",
"vDo", "tBm", "vDm", "tBl", "vDl", "mDo", "tBv", "qbo", "vDv", "qbm", "mDl", "qbl", "Ebo",
"mDv", "gjo", "Ebm", "gjm", "Ebl", "gjl", "Ebv", "gjv", "yse", "gFz", "ysd", "wke", "xku",
"wkd", "xkt", "tAu", "vBu", "tAt", "vBt", "mBu", "qDu", "mBt", "qDt", "EDu", "gbu", "EDt",
"gbt", "ysF", "wkF", "xkh", "tAh", "vAx", "mAx", "qBx", "wek", "yFg", "zCr", "wec", "yFa",
"weE", "yFD", "weC", "weB", "sqk", "wfg", "yFr", "sqc", "wfa", "sqE", "wfD", "sqC", "sqB",
"lik", "srg", "wfr", "lic", "sra", "liE", "srD", "liC", "liB", "Cyk", "ljg", "srr", "Cyc",
"lja", "CyE", "ljD", "CyC", "CyB", "Czg", "ljr", "Cza", "CzD", "Czr", "yhc", "zaq", "arw",
"yhE", "zan", "any", "yhC", "alz", "yhB", "wdc", "yEq", "wvc", "wdE", "yEn", "wvE", "yhn",
"wvC", "wdB", "wvB", "snc", "wdq", "trc", "snE", "wdn", "trE", "wvn", "trC", "snB", "trB",
"lbc", "snq", "njc", "lbE", "snn", "njE", "trn", "njC", "lbB", "njB", "Cjc", "lbq", "azc",
"CjE", "lbn", "azE", "njn", "azC", "CjB", "azB", "Cjq", "azq", "Cjn", "azn", "zio", "irs",
"rfy", "zim", "inw", "rdz", "zil", "ily", "ikz", "ygo", "zaf", "afy", "yxo", "ziv", "ivy",
"adz", "yxm", "ygl", "itz", "yxl", "wco", "yEf", "wto", "wcm", "xvo", "yxv", "wcl", "xvm",
"wtl", "xvl", "slo", "wcv", "tno", "slm", "vro", "tnm", "sll", "vrm", "tnl", "vrl", "lDo",
"slv", "nbo", "lDm", "rjo", "nbm", "lDl", "rjm", "nbl", "rjl", "Cbo", "lDv", "ajo", "Cbm",
"izo", "ajm", "Cbl", "izm", "ajl", "izl", "Cbv", "ajv", "zie", "ifw", "rFz", "zid", "idy",
"icz", "yge", "aFz", "ywu", "ygd", "ihz", "ywt", "wce", "wsu", "wcd", "xtu", "wst", "xtt",
"sku", "tlu", "skt", "vnu", "tlt", "vnt", "lBu", "nDu", "lBt", "rbu", "nDt", "rbt", "CDu",
"abu", "CDt", "iju", "abt", "ijt", "ziF", "iFy", "iEz", "ygF", "ywh", "wcF", "wsh", "xsx",
"skh", "tkx", "vlx", "lAx", "nBx", "rDx", "CBx", "aDx", "ibx", "iCz", "wFc", "yCq", "wFE",
"yCn", "wFC", "wFB", "sfc", "wFq", "sfE", "wFn", "sfC", "sfB", "krc", "sfq", "krE", "sfn",
"krC", "krB", "Bjc", "krq", "BjE", "krn", "BjC", "BjB", "Bjq", "Bjn", "yao", "zDf", "Dfy",
"yam", "Ddz", "yal", "wEo", "yCf", "who", "wEm", "whm", "wEl", "whl", "sdo", "wEv", "svo",
"sdm", "svm", "sdl", "svl", "kno", "sdv", "lro", "knm", "lrm", "knl", "lrl", "Bbo", "knv",
"Djo", "Bbm", "Djm", "Bbl", "Djl", "Bbv", "Djv", "zbe", "bfw", "npz", "zbd", "bdy", "bcz",
"yae", "DFz", "yiu", "yad", "bhz", "yit", "wEe", "wgu", "wEd", "wxu", "wgt", "wxt", "scu",
"stu", "sct", "tvu", "stt", "tvt", "klu", "lnu", "klt", "nru", "lnt", "nrt", "BDu", "Dbu",
"BDt", "bju", "Dbt", "bjt", "jfs", "rpy", "jdw", "roz", "jcy", "jcj", "zbF", "bFy", "zjh",
"jhy", "bEz", "jgz", "yaF", "yih", "yyx", "wEF", "wgh", "wwx", "xxx", "sch", "ssx", "ttx",
"vvx", "kkx", "llx", "nnx", "rrx", "BBx", "DDx", "bbx", "jFw", "rmz", "jEy", "jEj", "bCz",
"jaz", "jCy", "jCj", "jBj", "wCo", "wCm", "wCl", "sFo", "wCv", "sFm", "sFl", "kfo", "sFv",
"kfm", "kfl", "Aro", "kfv", "Arm", "Arl", "Arv", "yDe", "Bpz", "yDd", "wCe", "wau", "wCd",
"wat", "sEu", "shu", "sEt", "sht", "kdu", "kvu", "kdt", "kvt", "Anu", "Bru", "Ant", "Brt",
"zDp", "Dpy", "Doz", "yDF", "ybh", "wCF", "wah", "wix", "sEh", "sgx", "sxx", "kcx", "ktx",
"lvx", "Alx", "Bnx", "Drx", "bpw", "nuz", "boy", "boj", "Dmz", "bqz", "jps", "ruy", "jow",
"ruj", "joi", "job", "bmy", "jqy", "bmj", "jqj", "jmw", "rtj", "jmi", "jmb", "blj", "jnj",
"jli", "jlb", "jkr", "sCu", "sCt", "kFu", "kFt", "Afu", "Aft", "wDh", "sCh", "sax", "kEx",
"khx", "Adx", "Avx", "Buz", "Duy", "Duj", "buw", "nxj", "bui", "bub", "Dtj", "bvj", "jus",
"rxi", "jug", "rxb", "jua", "juD", "bti", "jvi", "btb", "jvb", "jtg", "rwr", "jta", "jtD",
"bsr", "jtr", "jsq", "jsn", "Bxj", "Dxi", "Dxb", "bxg", "nyr", "bxa", "bxD", "Dwr", "bxr",
"bwq", "bwn", "pjk", "urw", "ejA", "pbs", "uny", "ebk", "pDw", "ulz", "eDs", "pBy", "eBw",
"zfc", "fjk", "prw", "zfE", "fbs", "pny", "zfC", "fDw", "plz", "zfB", "fBy", "yrc", "zfq",
"frw", "yrE", "zfn", "fny", "yrC", "flz", "yrB", "xjc", "yrq", "xjE", "yrn", "xjC", "xjB",
"uzc", "xjq", "uzE", "xjn", "uzC", "uzB", "pzc", "uzq", "pzE", "uzn", "pzC", "djA", "ors",
"ufy", "dbk", "onw", "udz", "dDs", "oly", "dBw", "okz", "dAy", "zdo", "drs", "ovy", "zdm",
"dnw", "otz", "zdl", "dly", "dkz", "yno", "zdv", "dvy", "ynm", "dtz", "ynl", "xbo", "ynv",
"xbm", "xbl", "ujo", "xbv", "ujm", "ujl", "ozo", "ujv", "ozm", "ozl", "crk", "ofw", "uFz",
"cns", "ody", "clw", "ocz", "cky", "ckj", "zcu", "cvw", "ohz", "zct", "cty", "csz", "ylu",
"cxz", "ylt", "xDu", "xDt", "ubu", "ubt", "oju", "ojt", "cfs", "oFy", "cdw", "oEz", "ccy",
"ccj", "zch", "chy", "cgz", "ykx", "xBx", "uDx", "cFw", "oCz", "cEy", "cEj", "caz", "cCy",
"cCj", "FjA", "mrs", "tfy", "Fbk", "mnw", "tdz", "FDs", "mly", "FBw", "mkz", "FAy", "zFo",
"Frs", "mvy", "zFm", "Fnw", "mtz", "zFl", "Fly", "Fkz", "yfo", "zFv", "Fvy", "yfm", "Ftz",
"yfl", "wro", "yfv", "wrm", "wrl", "tjo", "wrv", "tjm", "tjl", "mzo", "tjv", "mzm", "mzl",
"qrk", "vfw", "xpz", "hbA", "qns", "vdy", "hDk", "qlw", "vcz", "hBs", "qky", "hAw", "qkj",
"hAi", "Erk", "mfw", "tFz", "hrk", "Ens", "mdy", "hns", "qty", "mcz", "hlw", "Eky", "hky",
"Ekj", "hkj", "zEu", "Evw", "mhz", "zhu", "zEt", "hvw", "Ety", "zht", "hty", "Esz", "hsz",
"ydu", "Exz", "yvu", "ydt", "hxz", "yvt", "wnu", "xru", "wnt", "xrt", "tbu", "vju", "tbt",
"vjt", "mju", "mjt", "grA", "qfs", "vFy", "gnk", "qdw", "vEz", "gls", "qcy", "gkw", "qcj",
"gki", "gkb", "Efs", "mFy", "gvs", "Edw", "mEz", "gtw", "qgz", "gsy", "Ecj", "gsj", "zEh",
"Ehy", "zgx", "gxy", "Egz", "gwz", "ycx", "ytx", "wlx", "xnx", "tDx", "vbx", "mbx", "gfk",
"qFw", "vCz", "gds", "qEy", "gcw", "qEj", "gci", "gcb", "EFw", "mCz", "ghw", "EEy", "ggy",
"EEj", "ggj", "Eaz", "giz", "gFs", "qCy", "gEw", "qCj", "gEi", "gEb", "ECy", "gay", "ECj",
"gaj", "gCw", "qBj", "gCi", "gCb", "EBj", "gDj", "gBi", "gBb", "Crk", "lfw", "spz", "Cns",
"ldy", "Clw", "lcz", "Cky", "Ckj", "zCu", "Cvw", "lhz", "zCt", "Cty", "Csz", "yFu", "Cxz",
"yFt", "wfu", "wft", "sru", "srt", "lju", "ljt", "arA", "nfs", "tpy", "ank", "ndw", "toz",
"als", "ncy", "akw", "ncj", "aki", "akb", "Cfs", "lFy", "avs", "Cdw", "lEz", "atw", "ngz",
"asy", "Ccj", "asj", "zCh", "Chy", "zax", "axy", "Cgz", "awz", "yEx", "yhx", "wdx", "wvx",
"snx", "trx", "lbx", "rfk", "vpw", "xuz", "inA", "rds", "voy", "ilk", "rcw", "voj", "iks",
"rci", "ikg", "rcb", "ika", "afk", "nFw", "tmz", "ivk", "ads", "nEy", "its", "rgy", "nEj",
"isw", "aci", "isi", "acb", "isb", "CFw", "lCz", "ahw", "CEy", "ixw", "agy", "CEj", "iwy",
"agj", "iwj", "Caz", "aiz", "iyz", "ifA", "rFs", "vmy", "idk", "rEw", "vmj", "ics", "rEi",
"icg", "rEb", "ica", "icD", "aFs", "nCy", "ihs", "aEw", "nCj", "igw", "raj", "igi", "aEb",
"igb", "CCy", "aay", "CCj", "iiy", "aaj", "iij", "iFk", "rCw", "vlj", "iEs", "rCi", "iEg",
"rCb", "iEa", "iED", "aCw", "nBj", "iaw", "aCi", "iai", "aCb", "iab", "CBj", "aDj", "ibj",
"iCs", "rBi", "iCg", "rBb", "iCa", "iCD", "aBi", "iDi", "aBb", "iDb", "iBg", "rAr", "iBa",
"iBD", "aAr", "iBr", "iAq", "iAn", "Bfs", "kpy", "Bdw", "koz", "Bcy", "Bcj", "Bhy", "Bgz",
"yCx", "wFx", "sfx", "krx", "Dfk", "lpw", "suz", "Dds", "loy", "Dcw", "loj", "Dci", "Dcb",
"BFw", "kmz", "Dhw", "BEy", "Dgy", "BEj", "Dgj", "Baz", "Diz", "bfA", "nps", "tuy", "bdk",
"now", "tuj", "bcs", "noi", "bcg", "nob", "bca", "bcD", "DFs", "lmy", "bhs", "DEw", "lmj",
"bgw", "DEi", "bgi", "DEb", "bgb", "BCy", "Day", "BCj", "biy", "Daj", "bij", "rpk", "vuw",
"xxj", "jdA", "ros", "vui", "jck", "rog", "vub", "jcc", "roa", "jcE", "roD", "jcC", "bFk",
"nmw", "ttj", "jhk", "bEs", "nmi", "jgs", "rqi", "nmb", "jgg", "bEa", "jga", "bED", "jgD",
"DCw", "llj", "baw", "DCi", "jiw", "bai", "DCb", "jii", "bab", "jib", "BBj", "DDj", "bbj",
"jjj", "jFA", "rms", "vti", "jEk", "rmg", "vtb", "jEc", "rma", "jEE", "rmD", "jEC", "jEB",
"bCs", "nli", "jas", "bCg", "nlb", "jag", "rnb", "jaa", "bCD", "jaD", "DBi", "bDi", "DBb",
"jbi", "bDb", "jbb", "jCk", "rlg", "vsr", "jCc", "rla", "jCE", "rlD", "jCC", "jCB", "bBg",
"nkr", "jDg", "bBa", "jDa", "bBD", "jDD", "DAr", "bBr", "jDr", "jBc", "rkq", "jBE", "rkn",
"jBC", "jBB", "bAq", "jBq", "bAn", "jBn", "jAo", "rkf", "jAm", "jAl", "bAf", "jAv", "Apw",
"kez", "Aoy", "Aoj", "Aqz", "Bps", "kuy", "Bow", "kuj", "Boi", "Bob", "Amy", "Bqy", "Amj",
"Bqj", "Dpk", "luw", "sxj", "Dos", "lui", "Dog", "lub", "Doa", "DoD", "Bmw", "ktj", "Dqw",
"Bmi", "Dqi", "Bmb", "Dqb", "Alj", "Bnj", "Drj", "bpA", "nus", "txi", "bok", "nug", "txb",
"boc", "nua", "boE", "nuD", "boC", "boB", "Dms", "lti", "bqs", "Dmg", "ltb", "bqg", "nvb",
"bqa", "DmD", "bqD", "Bli", "Dni", "Blb", "bri", "Dnb", "brb", "ruk", "vxg", "xyr", "ruc",
"vxa", "ruE", "vxD", "ruC", "ruB", "bmk", "ntg", "twr", "jqk", "bmc", "nta", "jqc", "rva",
"ntD", "jqE", "bmC", "jqC", "bmB", "jqB", "Dlg", "lsr", "bng", "Dla", "jrg", "bna", "DlD",
"jra", "bnD", "jrD", "Bkr", "Dlr", "bnr", "jrr", "rtc", "vwq", "rtE", "vwn", "rtC", "rtB",
"blc", "nsq", "jnc", "blE", "nsn", "jnE", "rtn", "jnC", "blB", "jnB", "Dkq", "blq", "Dkn",
"jnq", "bln", "jnn", "rso", "vwf", "rsm", "rsl", "bko", "nsf", "jlo", "bkm", "jlm", "bkl",
"jll", "Dkf", "bkv", "jlv", "rse", "rsd", "bke", "jku", "bkd", "jkt", "Aey", "Aej", "Auw",
"khj", "Aui", "Aub", "Adj", "Avj", "Bus", "kxi", "Bug", "kxb", "Bua", "BuD", "Ati", "Bvi",
"Atb", "Bvb", "Duk", "lxg", "syr", "Duc", "lxa", "DuE", "lxD", "DuC", "DuB", "Btg", "kwr",
"Dvg", "lxr", "Dva", "BtD", "DvD", "Asr", "Btr", "Dvr", "nxc", "tyq", "nxE", "tyn", "nxC",
"nxB", "Dtc", "lwq", "bvc", "nxq", "lwn", "bvE", "DtC", "bvC", "DtB", "bvB", "Bsq", "Dtq",
"Bsn", "bvq", "Dtn", "bvn", "vyo", "xzf", "vym", "vyl", "nwo", "tyf", "rxo", "nwm", "rxm",
"nwl", "rxl", "Dso", "lwf", "bto", "Dsm", "jvo", "btm", "Dsl", "jvm", "btl", "jvl", "Bsf",
"Dsv", "btv", "jvv", "vye", "vyd", "nwe", "rwu", "nwd", "rwt", "Dse", "bsu", "Dsd", "jtu",
"bst", "jtt", "vyF", "nwF", "rwh", "DsF", "bsh", "jsx", "Ahi", "Ahb", "Axg", "kir", "Axa",
"AxD", "Agr", "Axr", "Bxc", "kyq", "BxE", "kyn", "BxC", "BxB", "Awq", "Bxq", "Awn", "Bxn",
"lyo", "szf", "lym", "lyl", "Bwo", "kyf", "Dxo", "lyv", "Dxm", "Bwl", "Dxl", "Awf", "Bwv",
"Dxv", "tze", "tzd", "lye", "nyu", "lyd", "nyt", "Bwe", "Dwu", "Bwd", "bxu", "Dwt", "bxt",
"tzF", "lyF", "nyh", "BwF", "Dwh", "bwx", "Aiq", "Ain", "Ayo", "kjf", "Aym", "Ayl", "Aif",
"Ayv", "kze", "kzd", "Aye", "Byu", "Ayd", "Byt", "szp" };
/* converts values into bar patterns - replacing Grand Zebu's true type font */
static char *PDFttf[35] = { "00000", "00001", "00010", "00011", "00100", "00101", "00110", "00111",
"01000", "01001", "01010", "01011", "01100", "01101", "01110", "01111", "10000", "10001",
"10010", "10011", "10100", "10101", "10110", "10111", "11000", "11001", "11010",
"11011", "11100", "11101", "11110", "11111", "01", "1111111101010100", "11111101000101001"};
/* MicroPDF417 coefficients from ISO/IEC 24728:2006 Annex F */
static int Microcoeffs[344] = {
/* k = 7 */
76, 925, 537, 597, 784, 691, 437,
/* k = 8 */
237, 308, 436, 284, 646, 653, 428, 379,
/* k = 9 */
567, 527, 622, 257, 289, 362, 501, 441, 205,
/* k = 10 */
377, 457, 64, 244, 826, 841, 818, 691, 266, 612,
/* k = 11 */
462, 45, 565, 708, 825, 213, 15, 68, 327, 602, 904,
/* k = 12 */
597, 864, 757, 201, 646, 684, 347, 127, 388, 7, 69, 851,
/* k = 13 */
764, 713, 342, 384, 606, 583, 322, 592, 678, 204, 184, 394, 692,
/* k = 14 */
669, 677, 154, 187, 241, 286, 274, 354, 478, 915, 691, 833, 105, 215,
/* k = 15 */
460, 829, 476, 109, 904, 664, 230, 5, 80, 74, 550, 575, 147, 868, 642,
/* k = 16 */
274, 562, 232, 755, 599, 524, 801, 132, 295, 116, 442, 428, 295, 42, 176, 65,
/* k = 18 */
279, 577, 315, 624, 37, 855, 275, 739, 120, 297, 312, 202, 560, 321, 233, 756,
760, 573,
/* k = 21 */
108, 519, 781, 534, 129, 425, 681, 553, 422, 716, 763, 693, 624, 610, 310, 691,
347, 165, 193, 259, 568,
/* k = 26 */
443, 284, 887, 544, 788, 93, 477, 760, 331, 608, 269, 121, 159, 830, 446, 893,
699, 245, 441, 454, 325, 858, 131, 847, 764, 169,
/* k = 32 */
361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517,
273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410,
/* k = 38 */
234, 228, 438, 848, 133, 703, 529, 721, 788, 322, 280, 159, 738, 586, 388, 684,
445, 680, 245, 595, 614, 233, 812, 32, 284, 658, 745, 229, 95, 689, 920, 771,
554, 289, 231, 125, 117, 518,
/* k = 44 */
476, 36, 659, 848, 678, 64, 764, 840, 157, 915, 470, 876, 109, 25, 632, 405,
417, 436, 714, 60, 376, 97, 413, 706, 446, 21, 3, 773, 569, 267, 272, 213,
31, 560, 231, 758, 103, 271, 572, 436, 339, 730, 82, 285,
/* k = 50 */
923, 797, 576, 875, 156, 706, 63, 81, 257, 874, 411, 416, 778, 50, 205, 303,
188, 535, 909, 155, 637, 230, 534, 96, 575, 102, 264, 233, 919, 593, 865, 26,
579, 623, 766, 146, 10, 739, 246, 127, 71, 244, 211, 477, 920, 876, 427, 820,
718, 435 };
/* rows, columns, error codewords, k-offset of valid MicroPDF417 sizes from ISO/IEC 24728:2006 */
static int MicroVariants[170] =
{ 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
11, 14, 17, 20, 24, 28, 8, 11, 14, 17, 20, 23, 26, 6, 8, 10, 12, 15, 20, 26, 32, 38, 44, 4, 6, 8, 10, 12, 15, 20, 26, 32, 38, 44,
7, 7, 7, 8, 8, 8, 8, 9, 9, 10, 11, 13, 15, 12, 14, 16, 18, 21, 26, 32, 38, 44, 50, 8, 12, 14, 16, 18, 21, 26, 32, 38, 44, 50,
0, 0, 0, 7, 7, 7, 7, 15, 15, 24, 34, 57, 84, 45, 70, 99, 115, 133, 154, 180, 212, 250, 294, 7, 45, 70, 99, 115, 133, 154, 180, 212, 250, 294 };
/* rows, columns, error codewords, k-offset */
/* following is Left RAP, Centre RAP, Right RAP and Start Cluster from ISO/IEC 24728:2006 tables 10, 11 and 12 */
static int RAPTable[136] =
{ 1, 8, 36, 19, 9, 25, 1, 1, 8, 36, 19, 9, 27, 1, 7, 15, 25, 37, 1, 1, 21, 15, 1, 47, 1, 7, 15, 25, 37, 1, 1, 21, 15, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 7, 15, 25, 37, 17, 9, 29, 31, 25, 19, 1, 7, 15, 25, 37, 17, 9, 29, 31, 25,
9, 8, 36, 19, 17, 33, 1, 9, 8, 36, 19, 17, 35, 1, 7, 15, 25, 37, 33, 17, 37, 47, 49, 43, 1, 7, 15, 25, 37, 33, 17, 37, 47, 49,
0, 3, 6, 0, 6, 0, 0, 0, 3, 6, 0, 6, 6, 0, 0, 6, 0, 0, 0, 0, 6, 6, 0, 3, 0, 0, 6, 0, 0, 0, 0, 6, 6, 0 };
/* Left and Right Row Address Pattern from Table 2 */
static char *RAPLR[53] = {"", "221311", "311311", "312211", "222211", "213211", "214111", "223111",
"313111", "322111", "412111", "421111", "331111", "241111", "232111", "231211", "321211",
"411211", "411121", "411112", "321112", "312112", "311212", "311221", "311131", "311122",
"311113", "221113", "221122", "221131", "221221", "222121", "312121", "321121", "231121",
"231112", "222112", "213112", "212212", "212221", "212131", "212122", "212113", "211213",
"211123", "211132", "211141", "211231", "211222", "211312", "211321", "211411", "212311" };
/* Centre Row Address Pattern from Table 2 */
static char *RAPC[53] = {"", "112231", "121231", "122131", "131131", "131221", "132121", "141121",
"141211", "142111", "133111", "132211", "131311", "122311", "123211", "124111", "115111",
"114211", "114121", "123121", "123112", "122212", "122221", "121321", "121411", "112411",
"113311", "113221", "113212", "113122", "122122", "131122", "131113", "122113", "113113",
"112213", "112222", "112312", "112321", "111421", "111331", "111322", "111232", "111223",
"111133", "111124", "111214", "112114", "121114", "121123", "121132", "112132", "112141" };
void byteprocess(int *chainemc, int *mclength, unsigned char chaine[], int start, int length, int block);

496
backend/plessey.c Normal file
View file

@ -0,0 +1,496 @@
/* plessey.c - Handles Plessey and MSI Plessey */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#define SSET "0123456789ABCDEF"
static char *PlessTable[16] = {"13131313", "31131313", "13311313", "31311313", "13133113", "31133113",
"13313113", "31313113", "13131331", "31131331", "13311331", "31311331", "13133131",
"31133131", "13313131", "31313131"};
static char *MSITable[10] = {"12121212", "12121221", "12122112", "12122121", "12211212", "12211221",
"12212112", "12212121", "21121212", "21121221"};
int plessey(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Not MSI/Plessey but the older Plessey standard */
unsigned int i, check;
unsigned char *checkptr;
static char grid[9] = {1,1,1,1,0,1,0,0,1};
char dest[1024]; /* 8 + 65 * 8 + 8 * 2 + 9 + 1 ~ 1024 */
int error_number;
error_number = 0;
if(length > 65) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(SSET, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
checkptr = (unsigned char *)calloc (1, length * 4 + 8);
/* Start character */
strcpy(dest, "31311331");
/* Data area */
for(i = 0; i < length; i++)
{
check = posn(SSET, source[i]);
lookup(SSET, PlessTable, source[i], dest);
checkptr[4*i] = check & 1;
checkptr[4*i+1] = (check >> 1) & 1;
checkptr[4*i+2] = (check >> 2) & 1;
checkptr[4*i+3] = (check >> 3) & 1;
}
/* CRC check digit code adapted from code by Leonid A. Broukhis
used in GNU Barcode */
for (i = 0; i < (4 * length); i++) {
int j;
if (checkptr[i])
for (j = 0; j < 9; j++)
checkptr[i+j] ^= grid[j];
}
for (i = 0; i < 8; i++) {
switch(checkptr[length * 4 + i])
{
case 0: concat(dest, "13"); break;
case 1: concat(dest, "31"); break;
}
}
/* Stop character */
concat(dest, "331311313");
expand(symbol, dest);
ustrcpy(symbol->text, source);
free(checkptr);
return error_number;
}
int msi_plessey(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Plain MSI Plessey - does not calculate any check character */
unsigned int i;
char dest[512]; /* 2 + 55 * 8 + 3 + 1 ~ 512 */
if(length > 55) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
/* start character */
strcpy(dest, "21");
for(i = 0; i < length; i++)
{
lookup(NEON, MSITable, source[i], dest);
}
/* Stop character */
concat (dest, "121");
expand(symbol, dest);
ustrcpy(symbol->text, source);
return 0;
}
int msi_plessey_mod10(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* MSI Plessey with Modulo 10 check digit - algorithm from Barcode Island
http://www.barcodeisland.com/ */
unsigned long i, wright, dau, pedwar, pump, n;
char un[200], tri[32];
int error_number, h;
char dest[1000];
error_number = 0;
if(length > 18) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
/* start character */
strcpy(dest, "21");
/* draw data section */
for(i = 0; i < length; i++)
{
lookup(NEON, MSITable, source[i], dest);
}
/* caluculate check digit */
wright = 0;
n = ((length % 2) == 0) ? 1 : 0;
for(i = n; i < length; i += 2)
{
un[wright++] = source[i];
}
un[wright] = '\0';
dau = strtoul(un, NULL, 10);
dau *= 2;
sprintf(tri, "%ld", dau);
pedwar = 0;
h = strlen(tri);
for(i = 0; i < h; i++)
{
pedwar += ctoi(tri[i]);
}
n = length % 2;
for(i = n; i < length; i+=2)
{
pedwar += ctoi(source[i]);
}
pump = (10 - pedwar % 10);
if(pump == 10)
{
pump = 0;
}
/* draw check digit */
lookup(NEON, MSITable, itoc(pump), dest);
/* Stop character */
concat (dest, "121");
expand(symbol, dest);
ustrcpy(symbol->text, source);
symbol->text[length] = itoc(pump);
symbol->text[length + 1] = '\0';
return error_number;
}
int msi_plessey_mod1010(struct zint_symbol *symbol, unsigned char source[], const unsigned int src_len)
{ /* MSI Plessey with two Modulo 10 check digits - algorithm from
Barcode Island http://www.barcodeisland.com/ */
unsigned long i, n, wright, dau, pedwar, pump, chwech;
char un[16], tri[32];
int error_number, h;
char dest[1000];
error_number = 0;
if(src_len > 18) { /* No Entry Stack Smashers! limit because of str->number conversion*/
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
/* start character */
strcpy(dest, "21");
/* draw data section */
for(i = 0; i < src_len; i++)
{
lookup(NEON, MSITable, source[i], dest);
}
/* calculate first check digit */
wright = 0;
n = ((src_len %2) == 0) ? 1 : 0;
for(i = n; i < src_len; i += 2)
{
un[wright++] = source[i];
}
un[wright] = '\0';
dau = strtoul(un, NULL, 10);
dau *= 2;
sprintf(tri, "%ld", dau);
pedwar = 0;
h = strlen(tri);
for(i = 0; i < h; i++)
{
pedwar += ctoi(tri[i]);
}
n = src_len % 2;
for(i = n; i < src_len; i += 2)
{
pedwar += ctoi(source[i]);
}
pump = 10 - pedwar % 10;
if(pump == 10)
{
pump = 0;
}
/* calculate second check digit */
wright = 0;
n = src_len % 2;
for(i = n; i < src_len; i += 2)
{
un[wright++] = source[i];
}
un[wright++] = itoc(pump);
un[wright] = '\0';
dau = strtoul(un, NULL, 10);
dau *= 2;
sprintf(tri, "%ld", dau);
pedwar = 0;
h = strlen(tri);
for(i = 0; i < h; i++)
{
pedwar += ctoi(tri[i]);
}
i = ((src_len % 2) == 0) ? 1 : 0;
for(; i < src_len; i += 2)
{
pedwar += ctoi(source[i]);
}
chwech = 10 - pedwar % 10;
if(chwech == 10)
{
chwech = 0;
}
/* Draw check digits */
lookup(NEON, MSITable, itoc(pump), dest);
lookup(NEON, MSITable, itoc(chwech), dest);
/* Stop character */
concat (dest, "121");
expand(symbol, dest);
ustrcpy(symbol->text, source);
symbol->text[src_len] = itoc(pump);
symbol->text[src_len + 1] = itoc(chwech);
symbol->text[src_len + 2] = '\0';
return error_number;
}
int msi_plessey_mod11(struct zint_symbol *symbol, unsigned char source[], const unsigned int src_len)
{
/* Calculate a Modulo 11 check digit using the system discussed on Wikipedia -
see http://en.wikipedia.org/wiki/Talk:MSI_Barcode */
/* uses the IBM weight system */
int i, weight, x, check;
int error_number;
char dest[1000];
error_number = 0;
if(src_len > 55) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
/* start character */
strcpy(dest, "21");
/* draw data section */
for(i = 0; i < src_len; i++)
{
lookup(NEON, MSITable, source[i], dest);
}
/* calculate check digit */
x = 0;
weight = 2;
for(i = src_len - 1; i >= 0; i--) {
x += weight * ctoi(source[i]);
weight++;
if(weight > 7) {
weight = 2;
}
}
check = (11 - (x % 11)) % 11;
if(check == 10) {
lookup(NEON, MSITable, '1', dest);
lookup(NEON, MSITable, '0', dest);
} else {
lookup(NEON, MSITable, itoc(check), dest);
}
/* stop character */
concat (dest, "121");
expand(symbol, dest);
ustrcpy(symbol->text, source);
if(check == 10) {
concat((char* )symbol->text, "10");
} else {
symbol->text[src_len] = itoc(check);
symbol->text[src_len + 1] = '\0';
}
return error_number;
}
int msi_plessey_mod1110(struct zint_symbol *symbol, unsigned char source[], const unsigned int src_len)
{
/* Combining the Barcode Island and Wikipedia code */
/* Verified against http://www.bokai.com/BarcodeJSP/applet/BarcodeSampleApplet.htm */
/* Weighted using the IBM system */
unsigned long i, weight, x, check, wright, dau, pedwar, pump, h;
char un[16], tri[16];
int error_number;
char dest[1000];
unsigned char temp[32];
unsigned int temp_len;
error_number = 0;
if(src_len > 18) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
/* start character */
strcpy(dest, "21");
/* draw data section */
for(i = 0; i < src_len; i++)
{
lookup(NEON, MSITable, source[i], dest);
}
/* calculate first (mod 11) digit */
x = 0;
weight = 2;
for(i = src_len - 1; i >= 0; i--) {
x += weight * ctoi(source[i]);
weight++;
if(weight > 7) {
weight = 2;
}
}
check = (11 - (x % 11)) % 11;
ustrcpy(temp, source);
temp_len = src_len;
if(check == 10) {
lookup(NEON, MSITable, '1', dest);
lookup(NEON, MSITable, '0', dest);
uconcat(temp, (unsigned char *)"10");
temp_len += 2;
} else {
lookup(NEON, MSITable, itoc(check), dest);
temp[temp_len++] = itoc(check);
temp[temp_len] = '\0';
}
/* caluculate second (mod 10) check digit */
wright = 0;
i = ((temp_len % 2) == 0) ? 1 : 0;
for(; i < temp_len; i += 2)
{
un[wright++] = temp[i];
}
un[wright] = '\0';
dau = strtoul(un, NULL, 10);
dau *= 2;
sprintf(tri, "%ld", dau);
pedwar = 0;
h = strlen(tri);
for(i = 0; i < h; i++)
{
pedwar += ctoi(tri[i]);
}
i = temp_len % 2;
for(; i < temp_len; i+=2)
{
pedwar += ctoi(temp[i]);
}
pump = 10 - pedwar % 10;
if(pump == 10)
{
pump = 0;
}
/* draw check digit */
lookup(NEON, MSITable, itoc(pump), dest);
/* stop character */
concat (dest, "121");
expand(symbol, dest);
temp[temp_len++] = itoc(pump);
temp[temp_len] = '\0';
ustrcpy(symbol->text, temp);
return error_number;
}
int msi_handle(struct zint_symbol *symbol, unsigned char source[], int length) {
int error_number;
error_number = is_sane(NEON, source, length);
if(error_number != 0) {
strcpy(symbol->errtxt, "Invalid characters in input data");
return ERROR_INVALID_DATA;
}
if((symbol->option_2 < 0) || (symbol->option_2 > 4)) {
symbol->option_2 = 0;
}
switch(symbol->option_2) {
case 0: error_number = msi_plessey(symbol, source, length); break;
case 1: error_number = msi_plessey_mod10(symbol, source, length); break;
case 2: error_number = msi_plessey_mod1010(symbol, source, length); break;
case 3: error_number = msi_plessey_mod11(symbol, source, length); break;
case 4: error_number = msi_plessey_mod1110(symbol, source, length); break;
}
return error_number;
}

1138
backend/png.c Normal file

File diff suppressed because it is too large Load diff

603
backend/postal.c Normal file
View file

@ -0,0 +1,603 @@
/* postal.c - Handles PostNet, PLANET, FIM. RM4SCC and Flattermarken */
/* Zint - A barcode generating program using libpng
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
Including bug fixes by Bryan Hatton
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef _MSC_VER
#include <malloc.h>
#endif
#include "common.h"
#define DAFTSET "DAFT"
#define KRSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define KASUTSET "1234567890-abcdefgh"
#define CHKASUTSET "0123456789-abcdefgh"
#define SHKASUTSET "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ"
/* PostNet number encoding table - In this table L is long as S is short */
static char *PNTable[10] = {"LLSSS", "SSSLL", "SSLSL", "SSLLS", "SLSSL", "SLSLS", "SLLSS", "LSSSL",
"LSSLS", "LSLSS"};
static char *PLTable[10] = {"SSLLL", "LLLSS", "LLSLS", "LLSSL", "LSLLS", "LSLSL", "LSSLL", "SLLLS",
"SLLSL", "SLSLL"};
static char *RoyalValues[36] = {"11", "12", "13", "14", "15", "10", "21", "22", "23", "24", "25",
"20", "31", "32", "33", "34", "35", "30", "41", "42", "43", "44", "45", "40", "51", "52",
"53", "54", "55", "50", "01", "02", "03", "04", "05", "00"};
/* 0 = Full, 1 = Ascender, 2 = Descender, 3 = Tracker */
static char *RoyalTable[36] = {"3300", "3210", "3201", "2310", "2301", "2211", "3120", "3030", "3021",
"2130", "2121", "2031", "3102", "3012", "3003", "2112", "2103", "2013", "1320", "1230",
"1221", "0330", "0321", "0231", "1302", "1212", "1203", "0312", "0303", "0213", "1122",
"1032", "1023", "0132", "0123", "0033"};
static char *FlatTable[10] = {"0504", "18", "0117", "0216", "0315", "0414", "0513", "0612", "0711",
"0810"};
static char *KoreaTable[10] = {"1313150613", "0713131313", "0417131313", "1506131313",
"0413171313", "17171313", "1315061313", "0413131713", "17131713", "13171713"};
static char *JapanTable[19] = {"114", "132", "312", "123", "141", "321", "213", "231", "411", "144",
"414", "324", "342", "234", "432", "243", "423", "441", "111"};
int postnet(struct zint_symbol *symbol, unsigned char source[], char dest[], int length)
{
/* Handles the PostNet system used for Zip codes in the US */
unsigned int i, sum, check_digit;
int error_number;
error_number = 0;
if(length > 38) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
sum = 0;
/* start character */
strcpy(dest, "L");
for (i=0; i < length; i++)
{
lookup(NEON, PNTable, source[i], dest);
sum += ctoi(source[i]);
}
check_digit = (10 - (sum % 10)) % 10;
concat(dest, PNTable[check_digit]);
/* stop character */
concat (dest, "L");
return error_number;
}
int post_plot(struct zint_symbol *symbol, unsigned char source[], int length)
{
/* Puts PostNet barcodes into the pattern matrix */
char height_pattern[256]; /* 5 + 38 * 5 + 5 + 5 + 1 ~ 256 */
unsigned int loopey, h;
int writer;
int error_number;
error_number = 0;
error_number = postnet(symbol, source, height_pattern, length);
if(error_number != 0) {
return error_number;
}
writer = 0;
h = strlen(height_pattern);
for(loopey = 0; loopey < h; loopey++)
{
if(height_pattern[loopey] == 'L')
{
set_module(symbol, 0, writer);
}
set_module(symbol, 1, writer);
writer += 3;
}
symbol->row_height[0] = 6;
symbol->row_height[1] = 6;
symbol->rows = 2;
symbol->width = writer - 1;
return error_number;
}
int planet(struct zint_symbol *symbol, unsigned char source[], char dest[], int length)
{
/* Handles the PLANET system used for item tracking in the US */
unsigned int i, sum, check_digit;
int error_number;
error_number = 0;
if(length > 38) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
sum = 0;
/* start character */
strcpy(dest, "L");
for (i=0; i < length; i++)
{
lookup(NEON, PLTable, source[i], dest);
sum += ctoi(source[i]);
}
check_digit = (10 - (sum % 10)) % 10;
concat(dest, PLTable[check_digit]);
/* stop character */
concat (dest, "L");
return error_number;
}
int planet_plot(struct zint_symbol *symbol, unsigned char source[], int length)
{
/* Puts PLANET barcodes into the pattern matrix */
char height_pattern[256]; /* 5 + 38 * 5 + 5 + 5 + 1 ~ 256 */
unsigned int loopey, h;
int writer;
int error_number;
error_number = 0;
error_number = planet(symbol, source, height_pattern, length);
if(error_number != 0) {
return error_number;
}
writer = 0;
h = strlen(height_pattern);
for(loopey = 0; loopey < h; loopey++)
{
if(height_pattern[loopey] == 'L')
{
set_module(symbol, 0, writer);
}
set_module(symbol, 1, writer);
writer += 3;
}
symbol->row_height[0] = 6;
symbol->row_height[1] = 6;
symbol->rows = 2;
symbol->width = writer - 1;
return error_number;
}
int korea_post(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Korean Postal Authority */
int total, loop, check, zeroes, error_number;
char localstr[8], dest[80];
error_number = 0;
if(length > 6) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
zeroes = 6 - length;
memset(localstr, '0', zeroes);
strcpy(localstr + zeroes, (char *)source);
total = 0;
for(loop = 0; loop < 6; loop++) {
total += ctoi(localstr[loop]);
}
check = 10 - (total % 10);
if(check == 10) { check = 0; }
localstr[6] = itoc(check);
localstr[7] = '\0';
*dest = '\0';
for(loop = 5; loop >= 0; loop--) {
lookup(NEON, KoreaTable, localstr[loop], dest);
}
lookup(NEON, KoreaTable, localstr[6], dest);
expand(symbol, dest);
ustrcpy(symbol->text, (unsigned char*)localstr);
return error_number;
}
int fim(struct zint_symbol *symbol, unsigned char source[], int length)
{
/* The simplest barcode symbology ever! Supported by MS Word, so here it is! */
/* glyphs from http://en.wikipedia.org/wiki/Facing_Identification_Mark */
char dest[16] = { 0 };
if(length > 1) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
switch((char)source[0]) {
case 'a':
case 'A':
strcpy(dest, "111515111");
break;
case 'b':
case 'B':
strcpy(dest, "13111311131");
break;
case 'c':
case 'C':
strcpy(dest, "11131313111");
break;
case 'd':
case 'D':
strcpy(dest, "1111131311111");
break;
default:
strcpy(symbol->errtxt, "Invalid characters in data");
return ERROR_INVALID_DATA;
break;
}
expand(symbol, dest);
return 0;
}
char rm4scc(char source[], unsigned char dest[], int length)
{
/* Handles the 4 State barcodes used in the UK by Royal Mail */
unsigned int i;
int top, bottom, row, column, check_digit;
char values[3], set_copy[] = KRSET;
top = 0;
bottom = 0;
/* start character */
strcpy((char*)dest, "1");
for (i = 0; i < length; i++) {
lookup(KRSET, RoyalTable, source[i], (char*)dest);
strcpy(values, RoyalValues[posn(KRSET, source[i])]);
top += ctoi(values[0]);
bottom += ctoi(values[1]);
}
/* Calculate the check digit */
row = (top % 6) - 1;
column = (bottom % 6) - 1;
if(row == -1) { row = 5; }
if(column == -1) { column = 5; }
check_digit = (6 * row) + column;
concat((char*)dest, RoyalTable[check_digit]);
/* stop character */
concat ((char*)dest, "0");
return set_copy[check_digit];
}
int royal_plot(struct zint_symbol *symbol, unsigned char source[], int length)
{
/* Puts RM4SCC into the data matrix */
char height_pattern[200], check;
unsigned int loopey, h;
int writer;
int error_number;
strcpy(height_pattern, "");
error_number = 0;
if(length > 120) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
to_upper(source);
error_number = is_sane(KRSET, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
check = rm4scc((char*)source, (unsigned char*)height_pattern, length);
writer = 0;
h = strlen(height_pattern);
for(loopey = 0; loopey < h; loopey++)
{
if((height_pattern[loopey] == '1') || (height_pattern[loopey] == '0'))
{
set_module(symbol, 0, writer);
}
set_module(symbol, 1, writer);
if((height_pattern[loopey] == '2') || (height_pattern[loopey] == '0'))
{
set_module(symbol, 2, writer);
}
writer += 2;
}
symbol->row_height[0] = 4;
symbol->row_height[1] = 2;
symbol->row_height[2] = 4;
symbol->rows = 3;
symbol->width = writer - 1;
return error_number;
}
int kix_code(struct zint_symbol *symbol, unsigned char source[], int length)
{
/* Handles Dutch Post TNT KIX symbols */
/* The same as RM4SCC but without check digit */
/* Specification at http://www.tntpost.nl/zakelijk/klantenservice/downloads/kIX_code/download.aspx */
char height_pattern[50], localstr[13];
unsigned int loopey;
int writer, i, h;
int error_number; /* zeroes; */
strcpy(height_pattern, "");
error_number = 0;
if(length > 11) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
to_upper(source);
error_number = is_sane(KRSET, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
/* Add leading zeroes */
/* zeroes = 11 - length;
memset(localstr, '0', zeroes);
strcpy(localstr + zeroes, (char *)source);*/
strcpy(localstr, (char *)source);
/* Encode data */
for (i = 0; i < 11; i++) {
lookup(KRSET, RoyalTable, localstr[i], height_pattern);
}
writer = 0;
h = strlen(height_pattern);
for(loopey = 0; loopey < h; loopey++)
{
if((height_pattern[loopey] == '1') || (height_pattern[loopey] == '0'))
{
set_module(symbol, 0, writer);
}
set_module(symbol, 1, writer);
if((height_pattern[loopey] == '2') || (height_pattern[loopey] == '0'))
{
set_module(symbol, 2, writer);
}
writer += 2;
}
symbol->row_height[0] = 4;
symbol->row_height[1] = 2;
symbol->row_height[2] = 4;
symbol->rows = 3;
symbol->width = writer - 1;
return error_number;
}
int daft_code(struct zint_symbol *symbol, unsigned char source[], int length)
{
/* Handles DAFT Code symbols */
/* Presumably 'daft' doesn't mean the same thing in Germany as it does in the UK! */
char height_pattern[100];
unsigned int loopey, h;
int writer, i, error_number;
strcpy(height_pattern, "");
error_number = 0;
if(length > 50) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
to_upper((unsigned char*)source);
error_number = is_sane(DAFTSET, (unsigned char*)source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
for (i = 0; i < length; i++) {
if(source[i] == 'D') { concat(height_pattern, "2"); }
if(source[i] == 'A') { concat(height_pattern, "1"); }
if(source[i] == 'F') { concat(height_pattern, "0"); }
if(source[i] == 'T') { concat(height_pattern, "3"); }
}
writer = 0;
h = strlen(height_pattern);
for(loopey = 0; loopey < h; loopey++)
{
if((height_pattern[loopey] == '1') || (height_pattern[loopey] == '0'))
{
set_module(symbol, 0, writer);
}
set_module(symbol, 1, writer);
if((height_pattern[loopey] == '2') || (height_pattern[loopey] == '0'))
{
set_module(symbol, 2, writer);
}
writer += 2;
}
symbol->row_height[0] = 4;
symbol->row_height[1] = 2;
symbol->row_height[2] = 4;
symbol->rows = 3;
symbol->width = writer - 1;
return error_number;
}
int flattermarken(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Flattermarken - Not really a barcode symbology and (in my opinion) probably not much use
but it's supported by TBarCode so it's supported by Zint! */
int loop, error_number;
char dest[512]; /* 90 * 4 + 1 ~ */
error_number = 0;
if(length > 90) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
error_number = is_sane(NEON, source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
*dest = '\0';
for(loop = 0; loop < length; loop++) {
lookup(NEON, FlatTable, source[loop], dest);
}
expand(symbol, dest);
return error_number;
}
int japan_post(struct zint_symbol *symbol, unsigned char source[], int length)
{ /* Japanese Postal Code (Kasutama Barcode) */
int error_number, h;
char pattern[69];
int writer, loopey, inter_posn, i, sum, check;
char check_char;
char inter[23];
#ifndef _MSC_VER
char local_source[length + 1];
#else
char* local_source = (char*)_alloca(length + 1);
#endif
inter_posn = 0;
error_number = 0;
strcpy(local_source, (char*)source);
for(i = 0; i < length; i++) {
local_source[i] = source[i];
}
to_upper((unsigned char*)local_source);
error_number = is_sane(SHKASUTSET, (unsigned char*)local_source, length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
memset(inter, 'd', 20);/* Pad character CC4 */
inter[20] = '\0';
i = 0;
inter_posn = 0;
do {
if(((local_source[i] >= '0') && (local_source[i] <= '9')) || (local_source[i] == '-')) {
inter[inter_posn] = local_source[i];
inter_posn++;
} else {
if((local_source[i] >= 'A') && (local_source[i] <= 'J')) {
inter[inter_posn] = 'a';
inter[inter_posn + 1] = local_source[i] - 'A' + '0';
inter_posn += 2;
}
if((local_source[i] >= 'K') && (local_source[i] <= 'T')) {
inter[inter_posn] = 'b';
inter[inter_posn + 1] = local_source[i] - 'K' + '0';
inter_posn += 2;
}
if((local_source[i] >= 'U') && (local_source[i] <= 'Z')) {
inter[inter_posn] = 'c';
inter[inter_posn + 1] = local_source[i] - 'U' + '0';
inter_posn += 2;
}
}
i++;
}while((i < length) && (inter_posn < 20));
inter[20] = '\0';
strcpy(pattern, "13"); /* Start */
sum = 0;
for(i = 0; i < 20; i++) {
concat(pattern, JapanTable[posn(KASUTSET, inter[i])]);
sum += posn(CHKASUTSET, inter[i]);
/* printf("%c (%d)\n", inter[i], posn(CHKASUTSET, inter[i])); */
}
/* Calculate check digit */
check = 19 - (sum % 19);
if(check == 19) { check = 0; }
if(check <= 9) { check_char = check + '0'; }
if(check == 10) { check_char = '-'; }
if(check >= 11) { check_char = (check - 11) + 'a'; }
concat(pattern, JapanTable[posn(KASUTSET, check_char)]);
/* printf("check %c (%d)\n", check_char, check); */
concat(pattern, "31"); /* Stop */
/* Resolve pattern to 4-state symbols */
writer = 0;
h = strlen(pattern);
for(loopey = 0; loopey < h; loopey++)
{
if((pattern[loopey] == '2') || (pattern[loopey] == '1'))
{
set_module(symbol, 0, writer);
}
set_module(symbol, 1, writer);
if((pattern[loopey] == '3') || (pattern[loopey] == '1'))
{
set_module(symbol, 2, writer);
}
writer += 2;
}
symbol->row_height[0] = 2;
symbol->row_height[1] = 2;
symbol->row_height[2] = 2;
symbol->rows = 3;
symbol->width = writer - 1;
return error_number;
}

778
backend/ps.c Normal file
View file

@ -0,0 +1,778 @@
/* ps.c - Post Script output */
/*
libzint - the open source barcode library
Copyright (C) 2009 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <locale.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "common.h"
#define SSET "0123456789ABCDEF"
/* This file has expanded quite a bit since version 1.5 in order to accomodate
the formatting rules for EAN and UPC symbols as set out in EN 797:1995 - the
down side of this support is that the code is now vertually unreadable! */
int ps_plot(struct zint_symbol *symbol)
{
int i, block_width, latch, r, this_row;
float textpos, large_bar_height, preset_height, row_height, row_posn;
FILE *feps;
int fgred, fggrn, fgblu, bgred, bggrn, bgblu;
float red_ink, green_ink, blue_ink, red_paper, green_paper, blue_paper;
int error_number = 0;
int textoffset, xoffset, yoffset, textdone, main_width;
char textpart[10], addon[6];
int large_bar_count, comp_offset;
float addon_text_posn;
float scaler = symbol->scale;
float default_text_posn;
int plot_text = 1;
const char *locale = NULL;
row_height=0;
textdone = 0;
main_width = symbol->width;
strcpy(addon, "");
comp_offset = 0;
addon_text_posn = 0.0;
if((symbol->output_options & BARCODE_STDOUT) != 0) {
feps = stdout;
} else {
feps = fopen(symbol->outfile, "w");
}
if(feps == NULL) {
strcpy(symbol->errtxt, "Could not open output file");
return ERROR_FILE_ACCESS;
}
/* sort out colour options */
to_upper((unsigned char*)symbol->fgcolour);
to_upper((unsigned char*)symbol->bgcolour);
if(strlen(symbol->fgcolour) != 6) {
strcpy(symbol->errtxt, "Malformed foreground colour target");
return ERROR_INVALID_OPTION;
}
if(strlen(symbol->bgcolour) != 6) {
strcpy(symbol->errtxt, "Malformed background colour target");
return ERROR_INVALID_OPTION;
}
error_number = is_sane(SSET, (unsigned char*)symbol->fgcolour, strlen(symbol->fgcolour));
if (error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Malformed foreground colour target");
return ERROR_INVALID_OPTION;
}
error_number = is_sane(SSET, (unsigned char*)symbol->bgcolour, strlen(symbol->bgcolour));
if (error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Malformed background colour target");
return ERROR_INVALID_OPTION;
}
locale = setlocale(LC_ALL, "C");
fgred = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]);
fggrn = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]);
fgblu = (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]);
bgred = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]);
bggrn = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]);
bgblu = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]);
red_ink = fgred / 256.0;
green_ink = fggrn / 256.0;
blue_ink = fgblu / 256.0;
red_paper = bgred / 256.0;
green_paper = bggrn / 256.0;
blue_paper = bgblu / 256.0;
if (symbol->height == 0) {
symbol->height = 50;
}
large_bar_count = 0;
preset_height = 0.0;
for(i = 0; i < symbol->rows; i++) {
preset_height += symbol->row_height[i];
if(symbol->row_height[i] == 0) {
large_bar_count++;
}
}
large_bar_height = (symbol->height - preset_height) / large_bar_count;
if (large_bar_count == 0) {
symbol->height = preset_height;
}
while(!(module_is_set(symbol, symbol->rows - 1, comp_offset))) {
comp_offset++;
}
/* Certain symbols need whitespace otherwise characters get chopped off the sides */
if ((((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC))
|| (symbol->symbology == BARCODE_ISBNX)) {
switch(ustrlen(symbol->text)) {
case 13: /* EAN 13 */
case 16:
case 19:
if(symbol->whitespace_width == 0) {
symbol->whitespace_width = 10;
}
main_width = 96 + comp_offset;
break;
default:
main_width = 68 + comp_offset;
}
}
if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) {
if(symbol->whitespace_width == 0) {
symbol->whitespace_width = 10;
main_width = 96 + comp_offset;
}
}
if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) {
if(symbol->whitespace_width == 0) {
symbol->whitespace_width = 10;
main_width = 51 + comp_offset;
}
}
latch = 0;
r = 0;
/* Isolate add-on text */
if(is_extendable(symbol->symbology)) {
for(i = 0; i < ustrlen(symbol->text); i++) {
if (latch == 1) {
addon[r] = symbol->text[i];
r++;
}
if (symbol->text[i] == '+') {
latch = 1;
}
}
}
addon[r] = '\0';
if((symbol->show_hrt == 0) || (ustrlen(symbol->text) == 0)) {
plot_text = 0;
}
if(plot_text) {
textoffset = 9;
} else {
textoffset = 0;
}
xoffset = symbol->border_width + symbol->whitespace_width;
yoffset = symbol->border_width;
/* Start writing the header */
fprintf(feps, "%%!PS-Adobe-3.0 EPSF-3.0\n");
fprintf(feps, "%%%%Creator: Zint %s\n", ZINT_VERSION);
if(ustrlen(symbol->text) != 0) {
fprintf(feps, "%%%%Title: %s\n",symbol->text);
} else {
fprintf(feps, "%%%%Title: Zint Generated Symbol\n");
}
fprintf(feps, "%%%%Pages: 0\n");
if(symbol->symbology != BARCODE_MAXICODE) {
fprintf(feps, "%%%%BoundingBox: 0 0 %d %d\n", roundup((symbol->width + xoffset + xoffset) * scaler), roundup((symbol->height + textoffset + yoffset + yoffset) * scaler));
} else {
fprintf(feps, "%%%%BoundingBox: 0 0 %d %d\n", roundup((74.0 + xoffset + xoffset) * scaler), roundup((72.0 + yoffset + yoffset) * scaler));
}
fprintf(feps, "%%%%EndComments\n");
/* Definitions */
fprintf(feps, "/TL { setlinewidth moveto lineto stroke } bind def\n");
fprintf(feps, "/TC { moveto 0 360 arc 360 0 arcn fill } bind def\n");
fprintf(feps, "/TH { 0 setlinewidth moveto lineto lineto lineto lineto lineto closepath fill } bind def\n");
fprintf(feps, "/TB { 2 copy } bind def\n");
fprintf(feps, "/TR { newpath 4 1 roll exch moveto 1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath fill } bind def\n");
fprintf(feps, "/TE { pop pop } bind def\n");
fprintf(feps, "newpath\n");
/* Now the actual representation */
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_paper, green_paper, blue_paper);
fprintf(feps, "%.2f 0.00 TB 0.00 %.2f TR\n", (symbol->height + textoffset + yoffset + yoffset) * scaler, (symbol->width + xoffset + xoffset) * scaler);
if(((symbol->output_options & BARCODE_BOX) != 0) || ((symbol->output_options & BARCODE_BIND) != 0)) {
default_text_posn = 0.5 * scaler;
} else {
default_text_posn = (symbol->border_width + 0.5) * scaler;
}
if(symbol->symbology == BARCODE_MAXICODE) {
/* Maxicode uses hexagons */
float ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy, mx, my;
textoffset = 0.0;
if (((symbol->output_options & BARCODE_BOX) != 0) || ((symbol->output_options & BARCODE_BIND) != 0)) {
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, textoffset * scaler, 0.0, (74.0 + xoffset + xoffset) * scaler);
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, (textoffset + 72.0 + symbol->border_width) * scaler, 0.0, (74.0 + xoffset + xoffset) * scaler);
}
if((symbol->output_options & BARCODE_BOX) != 0) {
/* side bars */
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", (72.0 + (2 * symbol->border_width)) * scaler, textoffset * scaler, 0.0, symbol->border_width * scaler);
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", (72.0 + (2 * symbol->border_width)) * scaler, textoffset * scaler, (74.0 + xoffset + xoffset - symbol->border_width) * scaler, symbol->border_width * scaler);
}
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f TC\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 10.85 * scaler, (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 8.97 * scaler, (44.73 + xoffset) * scaler, (35.60 + yoffset) * scaler);
fprintf(feps, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f TC\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 7.10 * scaler, (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 5.22 * scaler, (40.98 + xoffset) * scaler, (35.60 + yoffset) * scaler);
fprintf(feps, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f TC\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 3.31 * scaler, (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 1.43 * scaler, (37.19 + xoffset) * scaler, (35.60 + yoffset) * scaler);
for(r = 0; r < symbol->rows; r++) {
for(i = 0; i < symbol->width; i++) {
if(module_is_set(symbol, r, i)) {
/* Dump a hexagon */
my = ((symbol->rows - r - 1)) * 2.135 + 1.43;
ay = my + 1.0 + yoffset;
by = my + 0.5 + yoffset;
cy = my - 0.5 + yoffset;
dy = my - 1.0 + yoffset;
ey = my - 0.5 + yoffset;
fy = my + 0.5 + yoffset;
if(r % 2 == 1) {
mx = (2.46 * i) + 1.23 + 1.23;
} else {
mx = (2.46 * i) + 1.23;
}
ax = mx + xoffset;
bx = mx + 0.86 + xoffset;
cx = mx + 0.86 + xoffset;
dx = mx + xoffset;
ex = mx - 0.86 + xoffset;
fx = mx - 0.86 + xoffset;
fprintf(feps, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f TH\n", ax * scaler, ay * scaler, bx * scaler, by * scaler, cx * scaler, cy * scaler, dx * scaler, dy * scaler, ex * scaler, ey * scaler, fx * scaler, fy * scaler);
}
}
}
}
if(symbol->symbology != BARCODE_MAXICODE) {
/* everything else uses rectangles (or squares) */
/* Works from the bottom of the symbol up */
int addon_latch = 0;
for(r = 0; r < symbol->rows; r++) {
this_row = symbol->rows - r - 1; /* invert r otherwise plots upside down */
if(symbol->row_height[this_row] == 0) {
row_height = large_bar_height;
} else {
row_height = symbol->row_height[this_row];
}
row_posn = 0;
for(i = 0; i < r; i++) {
if(symbol->row_height[symbol->rows - i - 1] == 0) {
row_posn += large_bar_height;
} else {
row_posn += symbol->row_height[symbol->rows - i - 1];
}
}
row_posn += (textoffset + yoffset);
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "%.2f %.2f ", row_height * scaler, row_posn * scaler);
i = 0;
if(module_is_set(symbol, this_row, 0)) {
latch = 1;
} else {
latch = 0;
}
do {
block_width = 0;
do {
block_width++;
} while (module_is_set(symbol, this_row, i + block_width) == module_is_set(symbol, this_row, i));
if((addon_latch == 0) && (r == 0) && (i > main_width)) {
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "%.2f %.2f ", (row_height - 5.0) * scaler, (row_posn - 5.0) * scaler);
addon_text_posn = row_posn + row_height - 8.0;
addon_latch = 1;
}
if(latch == 1) {
/* a bar */
fprintf(feps, "TB %.2f %.2f TR\n", (i + xoffset) * scaler, block_width * scaler);
latch = 0;
} else {
/* a space */
latch = 1;
}
i += block_width;
} while (i < symbol->width);
}
}
/* That's done the actual data area, everything else is human-friendly */
xoffset += comp_offset;
if (plot_text) {
if ((((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC)) ||
(symbol->symbology == BARCODE_ISBNX)) {
/* guard bar extensions and text formatting for EAN8 and EAN13 */
switch(ustrlen(symbol->text)) {
case 8: /* EAN-8 */
case 11:
case 14:
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "%.2f %.2f ", 5.0 * scaler, (4.0 + yoffset) * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (0 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (2 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (32 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (34 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (64 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (66 + xoffset) * scaler, 1 * scaler);
for(i = 0; i < 4; i++) {
textpart[i] = symbol->text[i];
}
textpart[4] = '\0';
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
textpos = 17;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
for(i = 0; i < 4; i++) {
textpart[i] = symbol->text[i + 4];
}
textpart[4] = '\0';
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
textpos = 50;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
textdone = 1;
switch(strlen(addon)) {
case 2:
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
textpos = xoffset + 86;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
fprintf(feps, " (%s) stringwidth\n", addon);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", addon);
fprintf(feps, "setmatrix\n");
break;
case 5:
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
textpos = xoffset + 100;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
fprintf(feps, " (%s) stringwidth\n", addon);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", addon);
fprintf(feps, "setmatrix\n");
break;
}
break;
case 13: /* EAN 13 */
case 16:
case 19:
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "%.2f %.2f ", 5.0 * scaler, (4.0 + yoffset) * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (0 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (2 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (46 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (48 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (92 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (94 + xoffset) * scaler, 1 * scaler);
textpart[0] = symbol->text[0];
textpart[1] = '\0';
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
textpos = -7;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
for(i = 0; i < 6; i++) {
textpart[i] = symbol->text[i + 1];
}
textpart[6] = '\0';
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
textpos = 24;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
for(i = 0; i < 6; i++) {
textpart[i] = symbol->text[i + 7];
}
textpart[6] = '\0';
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
textpos = 71;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
textdone = 1;
switch(strlen(addon)) {
case 2:
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
textpos = xoffset + 114;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
fprintf(feps, " (%s) stringwidth\n", addon);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", addon);
fprintf(feps, "setmatrix\n");
break;
case 5:
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
textpos = xoffset + 128;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
fprintf(feps, " (%s) stringwidth\n", addon);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", addon);
fprintf(feps, "setmatrix\n");
break;
}
break;
}
}
if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) {
/* guard bar extensions and text formatting for UPCA */
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "%.2f %.2f ", 5.0 * scaler, (4.0 + yoffset) * scaler);
latch = 1;
i = 0 + comp_offset;
do {
block_width = 0;
do {
block_width++;
} while (module_is_set(symbol, symbol->rows - 1, i + block_width) == module_is_set(symbol, symbol->rows - 1, i));
if(latch == 1) {
/* a bar */
fprintf(feps, "TB %.2f %.2f TR\n", (i + xoffset - comp_offset) * scaler, block_width * scaler);
latch = 0;
} else {
/* a space */
latch = 1;
}
i += block_width;
} while (i < 11 + comp_offset);
fprintf(feps, "TB %.2f %.2f TR\n", (46 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (48 + xoffset) * scaler, 1 * scaler);
latch = 1;
i = 85 + comp_offset;
do {
block_width = 0;
do {
block_width++;
} while (module_is_set(symbol, symbol->rows - 1, i + block_width) == module_is_set(symbol, symbol->rows - 1, i));
if(latch == 1) {
/* a bar */
fprintf(feps, "TB %.2f %.2f TR\n", (i + xoffset - comp_offset) * scaler, block_width * scaler);
latch = 0;
} else {
/* a space */
latch = 1;
}
i += block_width;
} while (i < 96 + comp_offset);
textpart[0] = symbol->text[0];
textpart[1] = '\0';
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 8.0 * scaler);
textpos = -5;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
for(i = 0; i < 5; i++) {
textpart[i] = symbol->text[i + 1];
}
textpart[5] = '\0';
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
textpos = 27;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
for(i = 0; i < 5; i++) {
textpart[i] = symbol->text[i + 6];
}
textpart[6] = '\0';
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
textpos = 68;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
textpart[0] = symbol->text[11];
textpart[1] = '\0';
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 8.0 * scaler);
textpos = 100;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
textdone = 1;
switch(strlen(addon)) {
case 2:
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
textpos = xoffset + 116;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
fprintf(feps, " (%s) stringwidth\n", addon);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", addon);
fprintf(feps, "setmatrix\n");
break;
case 5:
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
textpos = xoffset + 130;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
fprintf(feps, " (%s) stringwidth\n", addon);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", addon);
fprintf(feps, "setmatrix\n");
break;
}
}
if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) {
/* guard bar extensions and text formatting for UPCE */
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "%.2f %.2f ", 5.0 * scaler, (4.0 + yoffset) * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (0 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (2 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (46 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (48 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (50 + xoffset) * scaler, 1 * scaler);
textpart[0] = symbol->text[0];
textpart[1] = '\0';
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 8.0 * scaler);
textpos = -5;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
for(i = 0; i < 6; i++) {
textpart[i] = symbol->text[i + 1];
}
textpart[6] = '\0';
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
textpos = 24;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
textpart[0] = symbol->text[7];
textpart[1] = '\0';
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 8.0 * scaler);
textpos = 55;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
textdone = 1;
switch(strlen(addon)) {
case 2:
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
textpos = xoffset + 70;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
fprintf(feps, " (%s) stringwidth\n", addon);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", addon);
fprintf(feps, "setmatrix\n");
break;
case 5:
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
textpos = xoffset + 84;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
fprintf(feps, " (%s) stringwidth\n", addon);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", addon);
fprintf(feps, "setmatrix\n");
break;
}
}
} /* if (plot_text) */
xoffset -= comp_offset;
switch(symbol->symbology) {
case BARCODE_CODABLOCKF:
case BARCODE_HIBC_BLOCKF:
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, textoffset * scaler, xoffset * scaler, symbol->width * scaler);
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, (textoffset + symbol->height + symbol->border_width) * scaler, xoffset * scaler, symbol->width * scaler);
if(symbol->rows > 1) {
/* row binding */
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
for(r = 1; r < symbol->rows; r++) {
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", 2.0 * scaler, ((r * row_height) + textoffset + yoffset - 1) * scaler, (xoffset + 11) * scaler, (symbol->width - 24) * scaler);
}
}
break;
case BARCODE_MAXICODE:
/* Do nothing! (It's already been done) */
break;
default:
if((symbol->output_options & BARCODE_BIND) != 0) {
if((symbol->rows > 1) && (is_stackable(symbol->symbology) == 1)) {
/* row binding */
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
for(r = 1; r < symbol->rows; r++) {
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", 2.0 * scaler, ((r * row_height) + textoffset + yoffset - 1) * scaler, xoffset * scaler, symbol->width * scaler);
}
}
}
if (((symbol->output_options & BARCODE_BOX) != 0) || ((symbol->output_options & BARCODE_BIND) != 0)) {
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, textoffset * scaler, 0.0, (symbol->width + xoffset + xoffset) * scaler);
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, (textoffset + symbol->height + symbol->border_width) * scaler, 0.0, (symbol->width + xoffset + xoffset) * scaler);
}
if((symbol->output_options & BARCODE_BOX) != 0) {
/* side bars */
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", (symbol->height + (2 * symbol->border_width)) * scaler, textoffset * scaler, 0.0, symbol->border_width * scaler);
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", (symbol->height + (2 * symbol->border_width)) * scaler, textoffset * scaler, (symbol->width + xoffset + xoffset - symbol->border_width) * scaler, symbol->border_width * scaler);
}
break;
}
/* Put the human readable text at the bottom */
if(plot_text && (textdone == 0)) {
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", 8.0 * scaler);
textpos = symbol->width / 2.0;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", symbol->text);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", symbol->text);
fprintf(feps, "setmatrix\n");
}
fprintf(feps, "\nshowpage\n");
fclose(feps);
if (locale)
setlocale(LC_ALL, locale);
return error_number;
}

2464
backend/qr.c Normal file

File diff suppressed because it is too large Load diff

156
backend/qr.h Normal file
View file

@ -0,0 +1,156 @@
/* qr.h Data for QR Code */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
Copyright (C) 2006 Kentaro Fukuchi <fukuchi@megaui.net>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define LEVEL_L 1
#define LEVEL_M 2
#define LEVEL_Q 3
#define LEVEL_H 4
#define RHODIUM "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"
/* From ISO/IEC 18004:2006 Table 7 */
static int qr_data_codewords_L[] = {
19, 34, 55, 80, 108, 136, 156, 194, 232, 274, 324, 370, 428, 461, 523, 589, 647,
721, 795, 861, 932, 1006, 1094, 1174, 1276, 1370, 1468, 1531, 1631,
1735, 1843, 1955, 2071, 2191, 2306, 2434, 2566, 2702, 2812, 2956
};
static int qr_data_codewords_M[] = {
16, 28, 44, 64, 86, 108, 124, 154, 182, 216, 254, 290, 334, 365, 415, 453, 507,
563, 627, 669, 714, 782, 860, 914, 1000, 1062, 1128, 1193, 1267,
1373, 1455, 1541, 1631, 1725, 1812, 1914, 1992, 2102, 2216, 2334
};
static int qr_data_codewords_Q[] = {
13, 22, 34, 48, 62, 76, 88, 110, 132, 154, 180, 206, 244, 261, 295, 325, 367,
397, 445, 485, 512, 568, 614, 664, 718, 754, 808, 871, 911,
985, 1033, 1115, 1171, 1231, 1286, 1354, 1426, 1502, 1582, 1666
};
static int qr_data_codewords_H[] = {
9, 16, 26, 36, 46, 60, 66, 86, 100, 122, 140, 158, 180, 197, 223, 253, 283,
313, 341, 385, 406, 442, 464, 514, 538, 596, 628, 661, 701,
745, 793, 845, 901, 961, 986, 1054, 1096, 1142, 1222, 1276
};
static int qr_total_codewords[] = {
26, 44, 70, 100, 134, 172, 196, 242, 292, 346, 404, 466, 532, 581, 655, 733, 815,
901, 991, 1085, 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051,
2185, 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706
};
static int qr_blocks_L[] = {
1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12,
12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25
};
static int qr_blocks_M[] = {
1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20,
21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49
};
static int qr_blocks_Q[] = {
1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25,
27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68
};
static int qr_blocks_H[] = {
1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30,
32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81
};
static int qr_sizes[] = {
21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97,
101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177
};
static int micro_qr_sizes[] = {
11, 13, 15, 17
};
static int qr_align_loopsize[] = {
0, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7
};
static int qr_table_e1[] = {
6, 18, 0, 0, 0, 0, 0,
6, 22, 0, 0, 0, 0, 0,
6, 26, 0, 0, 0, 0, 0,
6, 30, 0, 0, 0, 0, 0,
6, 34, 0, 0, 0, 0, 0,
6, 22, 38, 0, 0, 0, 0,
6, 24, 42, 0, 0, 0, 0,
6, 26, 46, 0, 0, 0, 0,
6, 28, 50, 0, 0, 0, 0,
6, 30, 54, 0, 0, 0, 0,
6, 32, 58, 0, 0, 0, 0,
6, 34, 62, 0, 0, 0, 0,
6, 26, 46, 66, 0, 0, 0,
6, 26, 48, 70, 0, 0, 0,
6, 26, 50, 74, 0, 0, 0,
6, 30, 54, 78, 0, 0, 0,
6, 30, 56, 82, 0, 0, 0,
6, 30, 58, 86, 0, 0, 0,
6, 34, 62, 90, 0, 0, 0,
6, 28, 50, 72, 94, 0, 0,
6, 26, 50, 74, 98, 0, 0,
6, 30, 54, 78, 102, 0, 0,
6, 28, 54, 80, 106, 0, 0,
6, 32, 58, 84, 110, 0, 0,
6, 30, 58, 86, 114, 0, 0,
6, 34, 62, 90, 118, 0, 0,
6, 26, 50, 74, 98, 122, 0,
6, 30, 54, 78, 102, 126, 0,
6, 26, 52, 78, 104, 130, 0,
6, 30, 56, 82, 108, 134, 0,
6, 34, 60, 86, 112, 138, 0,
6, 30, 58, 86, 114, 142, 0,
6, 34, 62, 90, 118, 146, 0,
6, 30, 54, 78, 102, 126, 150,
6, 24, 50, 76, 102, 128, 154,
6, 28, 54, 80, 106, 132, 158,
6, 32, 58, 84, 110, 136, 162,
6, 26, 54, 82, 110, 138, 166,
6, 30, 58, 86, 114, 142, 170
};
static unsigned int qr_annex_c[] = {
/* Format information bit sequences */
0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, 0x77c4, 0x72f3, 0x7daa, 0x789d,
0x662f, 0x6318, 0x6c41, 0x6976, 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b,
0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed
};
static long int qr_annex_d[] = {
/* Version information bit sequences */
0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, 0x0f928, 0x10b78,
0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, 0x177ec, 0x18ec4, 0x191e1, 0x1afab,
0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b,
0x2542e, 0x26a64, 0x27541, 0x28c69
};
static int qr_annex_c1[] = {
/* Micro QR Code format information */
0x4445, 0x4172, 0x4e2b, 0x4b1c, 0x55ae, 0x5099, 0x5fc0, 0x5af7, 0x6793, 0x62a4, 0x6dfd, 0x68ca, 0x7678, 0x734f,
0x7c16, 0x7921, 0x06de, 0x03e9, 0x0cb0, 0x0987, 0x1735, 0x1202, 0x1d5b, 0x186c, 0x2508, 0x203f, 0x2f66, 0x2a51, 0x34e3,
0x31d4, 0x3e8d, 0x3bba
};

161
backend/reedsol.c Normal file
View file

@ -0,0 +1,161 @@
/**
*
* This is a simple Reed-Solomon encoder
* (C) Cliff Hones 2004
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
// It is not written with high efficiency in mind, so is probably
// not suitable for real-time encoding. The aim was to keep it
// simple, general and clear.
//
// <Some notes on the theory and implementation need to be added here>
// Usage:
// First call rs_init_gf(poly) to set up the Galois Field parameters.
// Then call rs_init_code(size, index) to set the encoding size
// Then call rs_encode(datasize, data, out) to encode the data.
//
// These can be called repeatedly as required - but note that
// rs_init_code must be called following any rs_init_gf call.
//
// If the parameters are fixed, some of the statics below can be
// replaced with constants in the obvious way, and additionally
// malloc/free can be avoided by using static arrays of a suitable
// size.
#include <stdio.h> // only needed for debug (main)
#include <stdlib.h> // only needed for malloc/free
#include "reedsol.h"
static int gfpoly;
static int symsize; // in bits
static int logmod; // 2**symsize - 1
static int rlen;
static int *logt = NULL, *alog = NULL, *rspoly = NULL;
// rs_init_gf(poly) initialises the parameters for the Galois Field.
// The symbol size is determined from the highest bit set in poly
// This implementation will support sizes up to 30 bits (though that
// will result in very large log/antilog tables) - bit sizes of
// 8 or 4 are typical
//
// The poly is the bit pattern representing the GF characteristic
// polynomial. e.g. for ECC200 (8-bit symbols) the polynomial is
// a**8 + a**5 + a**3 + a**2 + 1, which translates to 0x12d.
void rs_init_gf(int poly)
{
int m, b, p, v;
// Find the top bit, and hence the symbol size
for (b = 1, m = 0; b <= poly; b <<= 1)
m++;
b >>= 1;
m--;
gfpoly = poly;
symsize = m;
// Calculate the log/alog tables
logmod = (1 << m) - 1;
logt = (int *)malloc(sizeof(int) * (logmod + 1));
alog = (int *)malloc(sizeof(int) * logmod);
for (p = 1, v = 0; v < logmod; v++) {
alog[v] = p;
logt[p] = v;
p <<= 1;
if (p & b)
p ^= poly;
}
}
// rs_init_code(nsym, index) initialises the Reed-Solomon encoder
// nsym is the number of symbols to be generated (to be appended
// to the input data). index is usually 1 - it is the index of
// the constant in the first term (i) of the RS generator polynomial:
// (x + 2**i)*(x + 2**(i+1))*... [nsym terms]
// For ECC200, index is 1.
void rs_init_code(int nsym, int index)
{
int i, k;
rspoly = (int *)malloc(sizeof(int) * (nsym + 1));
rlen = nsym;
rspoly[0] = 1;
for (i = 1; i <= nsym; i++) {
rspoly[i] = 1;
for (k = i - 1; k > 0; k--) {
if (rspoly[k])
rspoly[k] = alog[(logt[rspoly[k]] + index) % logmod];
rspoly[k] ^= rspoly[k - 1];
}
rspoly[0] = alog[(logt[rspoly[0]] + index) % logmod];
index++;
}
}
void rs_encode(int len, unsigned char *data, unsigned char *res)
{
int i, k, m;
for (i = 0; i < rlen; i++)
res[i] = 0;
for (i = 0; i < len; i++) {
m = res[rlen - 1] ^ data[i];
for (k = rlen - 1; k > 0; k--) {
if (m && rspoly[k])
res[k] = res[k - 1] ^ alog[(logt[m] + logt[rspoly[k]]) % logmod];
else
res[k] = res[k - 1];
}
if (m && rspoly[0])
res[0] = alog[(logt[m] + logt[rspoly[0]]) % logmod];
else
res[0] = 0;
}
}
void rs_encode_long(int len, unsigned int *data, unsigned int *res)
{ /* The same as above but for larger bitlengths - Aztec code compatible */
int i, k, m;
for (i = 0; i < rlen; i++)
res[i] = 0;
for (i = 0; i < len; i++) {
m = res[rlen - 1] ^ data[i];
for (k = rlen - 1; k > 0; k--) {
if (m && rspoly[k])
res[k] = res[k - 1] ^ alog[(logt[m] + logt[rspoly[k]]) % logmod];
else
res[k] = res[k - 1];
}
if (m && rspoly[0])
res[0] = alog[(logt[m] + logt[rspoly[0]]) % logmod];
else
res[0] = 0;
}
}
void rs_free(void)
{ /* Free memory */
free(logt);
free(alog);
free(rspoly);
rspoly = NULL;
}

40
backend/reedsol.h Normal file
View file

@ -0,0 +1,40 @@
/**
*
* This is a simple Reed-Solomon encoder
* (C) Cliff Hones 2004
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __REEDSOL_H
#define __REEDSOL_H
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
extern void rs_init_gf(int poly);
extern void rs_init_code(int nsym, int index);
extern void rs_encode(int len, unsigned char *data, unsigned char *res);
extern void rs_encode_long(int len, unsigned int *data, unsigned int *res);
extern void rs_free(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __REEDSOL_H */

2367
backend/rss.c Normal file

File diff suppressed because it is too large Load diff

225
backend/rss.h Normal file
View file

@ -0,0 +1,225 @@
/* rss.h - Data tables for Reduced Space Symbology */
/*
libzint - the open source barcode library
Copyright (C) 2007 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define NUMERIC 110
#define ALPHA 97
#define ISOIEC 105
#define INVALID_CHAR 100
#define ANY_ENC 120
#define ALPHA_OR_ISO 121
/* RSS-14 Tables */
static int g_sum_table[9] = { 0, 161, 961, 2015, 2715, 0, 336, 1036, 1516};
static int t_table[9] = { 1, 10, 34, 70, 126, 4, 20, 48, 81};
static int modules_odd[9] = { 12, 10, 8, 6, 4, 5, 7, 9, 11 };
static int modules_even[9] = { 4, 6, 8, 10, 12, 10, 8, 6, 4 };
static int widest_odd[9] = { 8, 6, 4, 3, 1, 2, 4, 6, 8 };
static int widest_even[9] = { 1, 3, 5, 6, 8, 7, 5, 3, 1 };
static int widths[8];
static int finder_pattern[45] = {
3, 8, 2, 1, 1,
3, 5, 5, 1, 1,
3, 3, 7, 1, 1,
3, 1, 9, 1, 1,
2, 7, 4, 1, 1,
2, 5, 6, 1, 1,
2, 3, 8, 1, 1,
1, 5, 7, 1, 1,
1, 3, 9, 1, 1
};
static int checksum_weight[32] = { /* Table 5 */
1, 3, 9, 27, 2, 6, 18, 54,
4, 12, 36, 29, 8, 24, 72, 58,
16, 48, 65, 37, 32, 17, 51, 74,
64, 34, 23, 69, 49, 68, 46, 59
};
/* RSS Limited Tables */
static int t_even_ltd[7] = { 28, 728, 6454, 203, 2408, 1, 16632 };
static int modules_odd_ltd[7] = { 17, 13, 9, 15, 11, 19, 7 };
static int modules_even_ltd[7] = { 9, 13, 17, 11, 15, 7, 19 };
static int widest_odd_ltd[7] = { 6, 5, 3, 5, 4, 8, 1 };
static int widest_even_ltd[7] = { 3, 4, 6, 4, 5, 1, 8 };
static int checksum_weight_ltd[28] = { /* Table 7 */
1, 3, 9, 27, 81, 65, 17, 51, 64, 14, 42, 37, 22, 66,
20, 60, 2, 6, 18, 54, 73, 41, 34, 13, 39, 28, 84, 74
};
static int finder_pattern_ltd[1232] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 3, 2, 1, 1,
1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 3, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 3, 1, 1, 1,
1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 3, 2, 1, 1,
1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 3, 1, 1, 1,
1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 3, 1, 1, 1,
1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1,
1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1,
1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1,
1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 3, 1, 1, 1,
1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 3, 1, 1, 1,
1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1,
1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1,
1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1,
1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, 1,
1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 3, 1, 1, 1,
1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1,
1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 3, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 1, 1,
1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 2, 1, 1, 1,
1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 1,
1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 1, 1, 1,
1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 2, 1, 1, 1,
1, 1, 1, 1, 1, 3, 1, 1, 2, 1, 2, 1, 1, 1,
1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1,
1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1,
1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 2, 1, 1, 1,
1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 1, 1,
1, 1, 1, 3, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1,
1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1,
1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1,
1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 2, 1, 1, 1,
1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 2, 1, 1, 1,
1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1,
1, 3, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 3, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 2, 1, 1,
1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 2, 1, 1,
1, 1, 1, 2, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1,
1, 2, 1, 1, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1,
1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 3, 1, 1,
1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 1, 1,
1, 1, 1, 1, 1, 1, 2, 1, 1, 3, 2, 1, 1, 1,
1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1,
1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1,
1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1, 1,
1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1,
1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 2, 1, 1, 1,
1, 1, 1, 3, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1,
1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1,
1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 1,
1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1,
1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 3, 1, 1,
1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 2, 1, 1,
1, 1, 1, 1, 2, 1, 1, 1, 1, 3, 2, 1, 1, 1,
1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1,
1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 1, 1,
1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1,
1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1,
1, 2, 1, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1,
1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1,
1, 2, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1,
1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1,
1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1,
1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1,
1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1,
1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 1,
1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1,
1, 1, 2, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1,
1, 1, 2, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, 1,
1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1,
1, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, 1,
1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1,
2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1,
2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 1,
2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1,
2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1,
2, 1, 1, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, 1,
2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, 1,
2, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 1,
2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1
};
/* RSS Expanded Tables */
static int g_sum_exp[5] = { 0, 348, 1388, 2948, 3988 };
static int t_even_exp[5] = { 4, 20, 52, 104, 204 };
static int modules_odd_exp[5] = { 12, 10, 8, 6, 4 };
static int modules_even_exp[5] = { 5, 7, 9, 11, 13 };
static int widest_odd_exp[5] = { 7, 5, 4, 3, 1 };
static int widest_even_exp[5] = { 2, 4, 5, 6, 8 };
static int checksum_weight_exp[184] = { /* Table 14 */
1, 3, 9, 27, 81, 32, 96, 77,
20, 60, 180, 118, 143, 7, 21, 63,
189, 145, 13, 39, 117, 140, 209, 205,
193, 157, 49, 147, 19, 57, 171, 91,
62, 186, 136, 197, 169, 85, 44, 132,
185, 133, 188, 142, 4, 12, 36, 108,
113, 128, 173, 97, 80, 29, 87, 50,
150, 28, 84, 41, 123, 158, 52, 156,
46, 138, 203, 187, 139, 206, 196, 166,
76, 17, 51, 153, 37, 111, 122, 155,
43, 129, 176, 106, 107, 110, 119, 146,
16, 48, 144, 10, 30, 90, 59, 177,
109, 116, 137, 200, 178, 112, 125, 164,
70, 210, 208, 202, 184, 130, 179, 115,
134, 191, 151, 31, 93, 68, 204, 190,
148, 22, 66, 198, 172, 94, 71, 2,
6, 18, 54, 162, 64, 192, 154, 40,
120, 149, 25, 75, 14, 42, 126, 167,
79, 26, 78, 23, 69, 207, 199, 175,
103, 98, 83, 38, 114, 131, 182, 124,
161, 61, 183, 127, 170, 88, 53, 159,
55, 165, 73, 8, 24, 72, 5, 15,
45, 135, 194, 160, 58, 174, 100, 89
};
static int finder_pattern_exp[60] = { /* Table 15 */
1, 8, 4, 1, 1,
1, 1, 4, 8, 1,
3, 6, 4, 1, 1,
1, 1, 4, 6, 3,
3, 4, 6, 1, 1,
1, 1, 6, 4, 3,
3, 2, 8, 1, 1,
1, 1, 8, 2, 3,
2, 6, 5, 1, 1,
1, 1, 5, 6, 2,
2, 2, 9, 1, 1,
1, 1, 9, 2, 2
};
static int finder_sequence[198] = { /* Table 16 */
1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0,
1, 6, 3, 8, 0, 0, 0, 0, 0, 0, 0,
1, 10, 3, 8, 5, 0, 0, 0, 0, 0, 0,
1, 10, 3, 8, 7, 12, 0, 0, 0, 0, 0,
1, 10, 3, 8, 9, 12, 11, 0, 0, 0, 0,
1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0,
1, 2, 3, 4, 5, 6, 7, 10, 9, 0, 0,
1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 0,
1, 2, 3, 4, 5, 8, 7, 10, 9, 12, 11
};
static int weight_rows[210] = {
0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 5, 6, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 9, 10, 3, 4, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 17, 18, 3, 4, 13, 14, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 17, 18, 3, 4, 13, 14, 11, 12, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 17, 18, 3, 4, 13, 14, 15, 16, 21, 22, 19, 20, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 17, 18, 15, 16, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 17, 18, 19, 20, 21, 22, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 13, 14, 11, 12, 17, 18, 15, 16, 21, 22, 19, 20
};

6875
backend/sjis.h Normal file

File diff suppressed because it is too large Load diff

625
backend/svg.c Normal file
View file

@ -0,0 +1,625 @@
/* svg.c - Scalable Vector Graphics */
/*
libzint - the open source barcode library
Copyright (C) 2009 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <locale.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "common.h"
#define SSET "0123456789ABCDEF"
int svg_plot(struct zint_symbol *symbol)
{
int i, block_width, latch, r, this_row;
float textpos, large_bar_height, preset_height, row_height, row_posn = 0.0;
FILE *fsvg;
int fgred, fggrn, fgblu, bgred, bggrn, bgblu;
float red_ink, green_ink, blue_ink, red_paper, green_paper, blue_paper;
int error_number = 0;
int textoffset, xoffset, yoffset, textdone, main_width;
char textpart[10], addon[6];
int large_bar_count, comp_offset;
float addon_text_posn;
float scaler = symbol->scale;
float default_text_posn;
int plot_text = 1;
const char *locale = NULL;
row_height=0;
textdone = 0;
main_width = symbol->width;
strcpy(addon, "");
comp_offset = 0;
addon_text_posn = 0.0;
if((symbol->output_options & BARCODE_STDOUT) != 0) {
fsvg = stdout;
} else {
fsvg = fopen(symbol->outfile, "w");
}
if(fsvg == NULL) {
strcpy(symbol->errtxt, "Could not open output file");
return ERROR_FILE_ACCESS;
}
/* sort out colour options */
to_upper((unsigned char*)symbol->fgcolour);
to_upper((unsigned char*)symbol->bgcolour);
if(strlen(symbol->fgcolour) != 6) {
strcpy(symbol->errtxt, "Malformed foreground colour target");
return ERROR_INVALID_OPTION;
}
if(strlen(symbol->bgcolour) != 6) {
strcpy(symbol->errtxt, "Malformed background colour target");
return ERROR_INVALID_OPTION;
}
error_number = is_sane(SSET, (unsigned char*)symbol->fgcolour, strlen(symbol->fgcolour));
if (error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Malformed foreground colour target");
return ERROR_INVALID_OPTION;
}
error_number = is_sane(SSET, (unsigned char*)symbol->bgcolour, strlen(symbol->bgcolour));
if (error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Malformed background colour target");
return ERROR_INVALID_OPTION;
}
locale = setlocale(LC_ALL, "C");
fgred = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]);
fggrn = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]);
fgblu = (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]);
bgred = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]);
bggrn = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]);
bgblu = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]);
red_ink = fgred / 256.0;
green_ink = fggrn / 256.0;
blue_ink = fgblu / 256.0;
red_paper = bgred / 256.0;
green_paper = bggrn / 256.0;
blue_paper = bgblu / 256.0;
if (symbol->height == 0) {
symbol->height = 50;
}
large_bar_count = 0;
preset_height = 0.0;
for(i = 0; i < symbol->rows; i++) {
preset_height += symbol->row_height[i];
if(symbol->row_height[i] == 0) {
large_bar_count++;
}
}
large_bar_height = (symbol->height - preset_height) / large_bar_count;
if (large_bar_count == 0) {
symbol->height = preset_height;
}
while(!(module_is_set(symbol, symbol->rows - 1, comp_offset))) {
comp_offset++;
}
/* Certain symbols need whitespace otherwise characters get chopped off the sides */
if ((((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC))
|| (symbol->symbology == BARCODE_ISBNX)) {
switch(ustrlen(symbol->text)) {
case 13: /* EAN 13 */
case 16:
case 19:
if(symbol->whitespace_width == 0) {
symbol->whitespace_width = 10;
}
main_width = 96 + comp_offset;
break;
default:
main_width = 68 + comp_offset;
}
}
if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) {
if(symbol->whitespace_width == 0) {
symbol->whitespace_width = 10;
main_width = 96 + comp_offset;
}
}
if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) {
if(symbol->whitespace_width == 0) {
symbol->whitespace_width = 10;
main_width = 51 + comp_offset;
}
}
latch = 0;
r = 0;
/* Isolate add-on text */
if(is_extendable(symbol->symbology)) {
for(i = 0; i < ustrlen(symbol->text); i++) {
if (latch == 1) {
addon[r] = symbol->text[i];
r++;
}
if (symbol->text[i] == '+') {
latch = 1;
}
}
}
addon[r] = '\0';
if((symbol->show_hrt == 0) || (ustrlen(symbol->text) != 0)) {
plot_text = 0;
}
if(plot_text) {
textoffset = 9;
} else {
textoffset = 0;
}
xoffset = symbol->border_width + symbol->whitespace_width;
yoffset = symbol->border_width;
/* Start writing the header */
fprintf(fsvg, "<?xml version=\"1.0\" standalone=\"no\"?>\n");
fprintf(fsvg, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n");
fprintf(fsvg, " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
if(symbol->symbology != BARCODE_MAXICODE) {
fprintf(fsvg, "<svg width=\"%d\" height=\"%d\" version=\"1.1\"\n", roundup((symbol->width + xoffset + xoffset) * scaler), roundup((symbol->height + textoffset + yoffset + yoffset) * scaler));
} else {
fprintf(fsvg, "<svg width=\"%d\" height=\"%d\" version=\"1.1\"\n", roundup((74.0 + xoffset + xoffset) * scaler), roundup((72.0 + yoffset + yoffset) * scaler));
}
fprintf(fsvg, " xmlns=\"http://www.w3.org/2000/svg\">\n");
if(ustrlen(symbol->text) != 0) {
fprintf(fsvg, " <desc>%s\n", symbol->text);
} else {
fprintf(fsvg, " <desc>Zint Generated Symbol\n");
}
fprintf(fsvg, " </desc>\n");
fprintf(fsvg, "\n <g id=\"barcode\" fill=\"#%s\">\n", symbol->fgcolour);
if(symbol->symbology != BARCODE_MAXICODE) {
fprintf(fsvg, " <rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\" />\n", roundup((symbol->width + xoffset + xoffset) * scaler), roundup((symbol->height + textoffset + yoffset + yoffset) * scaler), symbol->bgcolour);
} else {
fprintf(fsvg, " <rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\" />\n", roundup((74.0 + xoffset + xoffset) * scaler), roundup((72.0 + yoffset + yoffset) * scaler), symbol->bgcolour);
}
if(((symbol->output_options & BARCODE_BOX) != 0) || ((symbol->output_options & BARCODE_BIND) != 0)) {
default_text_posn = (symbol->height + textoffset + symbol->border_width + symbol->border_width) * scaler;
} else {
default_text_posn = (symbol->height + textoffset + symbol->border_width) * scaler;
}
if(symbol->symbology == BARCODE_MAXICODE) {
/* Maxicode uses hexagons */
float ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy, mx, my;
textoffset = 0.0;
if (((symbol->output_options & BARCODE_BOX) != 0) || ((symbol->output_options & BARCODE_BIND) != 0)) {
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", 0.0, 0.0, (74.0 + xoffset + xoffset) * scaler, symbol->border_width * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", 0.0, (72.0 + symbol->border_width) * scaler, (74.0 + xoffset + xoffset) * scaler, symbol->border_width * scaler);
}
if((symbol->output_options & BARCODE_BOX) != 0) {
/* side bars */
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", 0.0, 0.0, symbol->border_width * scaler, (72.0 + (2 * symbol->border_width)) * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (74.0 + xoffset + xoffset - symbol->border_width) * scaler, 0.0, symbol->border_width * scaler, (72.0 + (2 * symbol->border_width)) * scaler);
}
fprintf(fsvg, " <circle cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\" fill=\"#%s\" />\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 10.85 * scaler, symbol->fgcolour);
fprintf(fsvg, " <circle cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\" fill=\"#%s\" />\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 8.97 * scaler, symbol->bgcolour);
fprintf(fsvg, " <circle cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\" fill=\"#%s\" />\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 7.10 * scaler, symbol->fgcolour);
fprintf(fsvg, " <circle cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\" fill=\"#%s\" />\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 5.22 * scaler, symbol->bgcolour);
fprintf(fsvg, " <circle cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\" fill=\"#%s\" />\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 3.31 * scaler, symbol->fgcolour);
fprintf(fsvg, " <circle cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\" fill=\"#%s\" />\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 1.43 * scaler, symbol->bgcolour);
for(r = 0; r < symbol->rows; r++) {
for(i = 0; i < symbol->width; i++) {
if(module_is_set(symbol, r, i)) {
/* Dump a hexagon */
my = r * 2.135 + 1.43;
ay = my + 1.0 + yoffset;
by = my + 0.5 + yoffset;
cy = my - 0.5 + yoffset;
dy = my - 1.0 + yoffset;
ey = my - 0.5 + yoffset;
fy = my + 0.5 + yoffset;
if(r % 2 == 1) {
mx = (2.46 * i) + 1.23 + 1.23;
} else {
mx = (2.46 * i) + 1.23;
}
ax = mx + xoffset;
bx = mx + 0.86 + xoffset;
cx = mx + 0.86 + xoffset;
dx = mx + xoffset;
ex = mx - 0.86 + xoffset;
fx = mx - 0.86 + xoffset;
fprintf(fsvg, " <path d=\"M %.2f %.2f L %.2f %.2f L %.2f %.2f L %.2f %.2f L %.2f %.2f L %.2f %.2f Z\" />\n", ax * scaler, ay * scaler, bx * scaler, by * scaler, cx * scaler, cy * scaler, dx * scaler, dy * scaler, ex * scaler, ey * scaler, fx * scaler, fy * scaler);
}
}
}
}
if(symbol->symbology != BARCODE_MAXICODE) {
/* everything else uses rectangles (or squares) */
/* Works from the bottom of the symbol up */
int addon_latch = 0;
for(r = 0; r < symbol->rows; r++) {
this_row = r;
if(symbol->row_height[this_row] == 0) {
row_height = large_bar_height;
} else {
row_height = symbol->row_height[this_row];
}
row_posn = 0;
for(i = 0; i < r; i++) {
if(symbol->row_height[i] == 0) {
row_posn += large_bar_height;
} else {
row_posn += symbol->row_height[i];
}
}
row_posn += yoffset;
i = 0;
if(module_is_set(symbol, this_row, 0)) {
latch = 1;
} else {
latch = 0;
}
do {
block_width = 0;
do {
block_width++;
} while (module_is_set(symbol, this_row, i + block_width) == module_is_set(symbol, this_row, i));
if((addon_latch == 0) && (r == (symbol->rows - 1)) && (i > main_width)) {
addon_text_posn = (row_posn + 8.0) * scaler;
addon_latch = 1;
}
if(latch == 1) {
/* a bar */
if(addon_latch == 0) {
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (i + xoffset) * scaler, row_posn * scaler, block_width * scaler, row_height * scaler);
} else {
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (i + xoffset) * scaler, (row_posn + 10.0) * scaler, block_width * scaler, (row_height - 5.0) * scaler);
}
latch = 0;
} else {
/* a space */
latch = 1;
}
i += block_width;
} while (i < symbol->width);
}
}
/* That's done the actual data area, everything else is human-friendly */
xoffset += comp_offset;
row_posn = (row_posn + large_bar_height) * scaler;
if(plot_text) {
if ((((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC)) ||
(symbol->symbology == BARCODE_ISBNX)) {
/* guard bar extensions and text formatting for EAN8 and EAN13 */
switch(ustrlen(symbol->text)) {
case 8: /* EAN-8 */
case 11:
case 14:
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (0 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (2 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (32 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (34 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (64 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (66 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
for(i = 0; i < 4; i++) {
textpart[i] = symbol->text[i];
}
textpart[4] = '\0';
textpos = 17;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 11.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
for(i = 0; i < 4; i++) {
textpart[i] = symbol->text[i + 4];
}
textpart[4] = '\0';
textpos = 50;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 11.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
textdone = 1;
switch(strlen(addon)) {
case 2:
textpos = xoffset + 86;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", textpos * scaler, addon_text_posn * scaler);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 11.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", addon);
fprintf(fsvg, " </text>\n");
break;
case 5:
textpos = xoffset + 100;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", textpos * scaler, addon_text_posn * scaler);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 11.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", addon);
fprintf(fsvg, " </text>\n");
break;
}
break;
case 13: /* EAN 13 */
case 16:
case 19:
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (0 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (2 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (46 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (48 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (92 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (94 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
textpart[0] = symbol->text[0];
textpart[1] = '\0';
textpos = -7;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 11.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
for(i = 0; i < 6; i++) {
textpart[i] = symbol->text[i + 1];
}
textpart[6] = '\0';
textpos = 24;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 11.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
for(i = 0; i < 6; i++) {
textpart[i] = symbol->text[i + 7];
}
textpart[6] = '\0';
textpos = 71;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 11.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
textdone = 1;
switch(strlen(addon)) {
case 2:
textpos = xoffset + 114;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", textpos * scaler, addon_text_posn * scaler);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 11.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", addon);
fprintf(fsvg, " </text>\n");
break;
case 5:
textpos = xoffset + 128;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", textpos * scaler, addon_text_posn * scaler);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 11.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", addon);
fprintf(fsvg, " </text>\n");
break;
}
break;
}
}
if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) {
/* guard bar extensions and text formatting for UPCA */
latch = 1;
i = 0 + comp_offset;
do {
block_width = 0;
do {
block_width++;
} while (module_is_set(symbol, symbol->rows - 1, i + block_width) == module_is_set(symbol, symbol->rows - 1, i));
if(latch == 1) {
/* a bar */
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (i + xoffset - comp_offset) * scaler, row_posn, block_width * scaler, 5.0 * scaler);
latch = 0;
} else {
/* a space */
latch = 1;
}
i += block_width;
} while (i < 11 + comp_offset);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (46 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (48 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
latch = 1;
i = 85 + comp_offset;
do {
block_width = 0;
do {
block_width++;
} while (module_is_set(symbol, symbol->rows - 1, i + block_width) == module_is_set(symbol, symbol->rows - 1, i));
if(latch == 1) {
/* a bar */
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (i + xoffset - comp_offset) * scaler, row_posn, block_width * scaler, 5.0 * scaler);
latch = 0;
} else {
/* a space */
latch = 1;
}
i += block_width;
} while (i < 96 + comp_offset);
textpart[0] = symbol->text[0];
textpart[1] = '\0';
textpos = -5;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 8.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
for(i = 0; i < 5; i++) {
textpart[i] = symbol->text[i + 1];
}
textpart[5] = '\0';
textpos = 27;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 11.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
for(i = 0; i < 5; i++) {
textpart[i] = symbol->text[i + 6];
}
textpart[6] = '\0';
textpos = 68;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 11.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
textpart[0] = symbol->text[11];
textpart[1] = '\0';
textpos = 100;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 8.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
textdone = 1;
switch(strlen(addon)) {
case 2:
textpos = xoffset + 116;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", textpos * scaler, addon_text_posn * scaler);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 11.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", addon);
fprintf(fsvg, " </text>\n");
break;
case 5:
textpos = xoffset + 130;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", textpos * scaler, addon_text_posn * scaler);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 11.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", addon);
fprintf(fsvg, " </text>\n");
break;
}
}
if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) {
/* guard bar extensions and text formatting for UPCE */
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (0 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (2 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (46 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (48 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (50 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
textpart[0] = symbol->text[0];
textpart[1] = '\0';
textpos = -5;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 8.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
for(i = 0; i < 6; i++) {
textpart[i] = symbol->text[i + 1];
}
textpart[6] = '\0';
textpos = 24;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 11.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
textpart[0] = symbol->text[7];
textpart[1] = '\0';
textpos = 55;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 8.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
textdone = 1;
switch(strlen(addon)) {
case 2:
textpos = xoffset + 70;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", textpos * scaler, addon_text_posn * scaler);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 11.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", addon);
fprintf(fsvg, " </text>\n");
break;
case 5:
textpos = xoffset + 84;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", textpos * scaler, addon_text_posn * scaler);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 11.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", addon);
fprintf(fsvg, " </text>\n");
break;
}
}
} /* if (plot_text) */
xoffset -= comp_offset;
switch(symbol->symbology) {
case BARCODE_CODABLOCKF:
case BARCODE_HIBC_BLOCKF:
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", xoffset * scaler, 0.0, symbol->width * scaler, symbol->border_width * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", xoffset * scaler, (symbol->height + symbol->border_width) * scaler, symbol->width * scaler, symbol->border_width * scaler);
if(symbol->rows > 1) {
/* row binding */
for(r = 1; r < symbol->rows; r++) {
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (xoffset + 11) * scaler, ((r * row_height) + yoffset - 1) * scaler, (symbol->width - 24) * scaler, 2.0 * scaler);
}
}
break;
case BARCODE_MAXICODE:
/* Do nothing! (It's already been done) */
break;
default:
if((symbol->output_options & BARCODE_BIND) != 0) {
if((symbol->rows > 1) && (is_stackable(symbol->symbology) == 1)) {
/* row binding */
for(r = 1; r < symbol->rows; r++) {
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", xoffset * scaler, ((r * row_height) + yoffset - 1) * scaler, symbol->width * scaler, 2.0 * scaler);
}
}
}
if (((symbol->output_options & BARCODE_BOX) != 0) || ((symbol->output_options & BARCODE_BIND) != 0)) {
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", 0.0, 0.0, (symbol->width + xoffset + xoffset) * scaler, symbol->border_width * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", 0.0, (symbol->height + symbol->border_width) * scaler, (symbol->width + xoffset + xoffset) * scaler, symbol->border_width * scaler);
}
if((symbol->output_options & BARCODE_BOX) != 0) {
/* side bars */
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", 0.0, 0.0, symbol->border_width * scaler, (symbol->height + (2 * symbol->border_width)) * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (symbol->width + xoffset + xoffset - symbol->border_width) * scaler, 0.0, symbol->border_width * scaler, (symbol->height + (2 * symbol->border_width)) * scaler);
}
break;
}
/* Put the human readable text at the bottom */
if(plot_text && (textdone == 0)) {
textpos = symbol->width / 2.0;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", 8.0 * scaler, symbol->fgcolour);
fprintf(fsvg, " %s\n", symbol->text);
fprintf(fsvg, " </text>\n");
}
fprintf(fsvg, " </g>\n");
fprintf(fsvg, "</svg>\n");
fclose(fsvg);
if (locale)
setlocale(LC_ALL, locale);
return error_number;
}

157
backend/telepen.c Normal file
View file

@ -0,0 +1,157 @@
/* telepen.c - Handles Telepen and Telepen numeric */
/*
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define SODIUM "0123456789X"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
static char *TeleTable[] =
{
"1111111111111111", "1131313111", "33313111", "1111313131", "3111313111", "11333131", "13133131", "111111313111",
"31333111", "1131113131", "33113131", "1111333111", "3111113131", "1113133111", "1311133111", "111111113131",
"3131113111", "11313331", "333331", "111131113111", "31113331", "1133113111", "1313113111", "1111113331",
"31131331", "113111113111", "3311113111", "1111131331", "311111113111", "1113111331", "1311111331", "11111111113111",
"31313311", "1131311131", "33311131", "1111313311", "3111311131", "11333311", "13133311", "111111311131",
"31331131", "1131113311", "33113311", "1111331131", "3111113311", "1113131131", "1311131131", "111111113311",
"3131111131", "1131131311", "33131311", "111131111131", "3111131311", "1133111131", "1313111131", "111111131311",
"3113111311", "113111111131", "3311111131", "111113111311", "311111111131", "111311111311", "131111111311", "11111111111131",
"3131311111", "11313133", "333133", "111131311111", "31113133", "1133311111", "1313311111", "1111113133",
"313333", "113111311111", "3311311111", "11113333", "311111311111", "11131333", "13111333", "11111111311111",
"31311133", "1131331111", "33331111", " 1111311133", "3111331111", "11331133", "13131133", "111111331111",
"3113131111", "1131111133", "33111133", "111113131111", "3111111133", "111311131111", "131111131111", "111111111133",
"31311313", "113131111111", "3331111111", "1111311313", "311131111111", "11331313", "13131313", "11111131111111",
"3133111111", "1131111313", "33111313", "111133111111", "3111111313", "111313111111", "131113111111", "111111111313",
"313111111111", "1131131113", "33131113", "11113111111111","3111131113", "113311111111", "131311111111", "111111131113",
"3113111113", "11311111111111","331111111111","111113111113", "31111111111111","111311111113","131111111113"};
int telepen(struct zint_symbol *symbol, unsigned char source[], int src_len)
{
unsigned int i, count, check_digit;
int error_number;
char dest[512]; /*14 + 30 * 14 + 14 + 14 + 1 ~ 512 */
error_number = 0;
count = 0;
if(src_len > 30) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
/* Start character */
strcpy(dest, TeleTable['_']);
for(i = 0; i < src_len; i++) {
if(source[i] > 127) {
/* Cannot encode extended ASCII */
strcpy(symbol->errtxt, "Invalid characters in input data");
return ERROR_INVALID_DATA;
}
concat(dest, TeleTable[source[i]]);
count += source[i];
}
check_digit = 127 - (count % 127);
if(check_digit == 127) { check_digit = 0; }
concat(dest, TeleTable[check_digit]);
/* Stop character */
concat(dest, TeleTable['z']);
expand(symbol, dest);
for(i = 0; i < src_len; i++) {
if(source[i] == '\0') {
symbol->text[i] = ' ';
} else {
symbol->text[i] = source[i];
}
}
symbol->text[src_len] = '\0';
return error_number;
}
int telepen_num(struct zint_symbol *symbol, unsigned char source[], int src_len)
{
unsigned int i, count, check_digit, glyph;
int error_number, temp_length = src_len;
char dest[1024]; /* 14 + 60 * 14 + 14 + 14 + 1 ~ 1024 */
unsigned char temp[64];
error_number = 0;
count = 0;
if(temp_length > 60) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
ustrcpy(temp, source);
to_upper(temp);
error_number = is_sane(NEON, temp, temp_length);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
/* Add a leading zero if required */
if ((temp_length % 2) != 0)
{
memmove(temp + 1, temp, temp_length);
temp[0] = '0';
temp[++temp_length] = '\0';
}
/* Start character */
strcpy(dest, TeleTable['_']);
for (i = 0; i < temp_length; i += 2)
{
if(temp[i] == 'X') {
strcpy(symbol->errtxt, "Invalid position of X in Telepen data");
return ERROR_INVALID_DATA;
}
if(temp[i + 1] == 'X') {
glyph = ctoi(temp[i]) + 17;
count += glyph;
} else {
glyph = (10 * ctoi(temp[i])) + ctoi(temp[i + 1]);
glyph += 27;
count += glyph;
}
concat(dest, TeleTable[glyph]);
}
check_digit = 127 - (count % 127);
if(check_digit == 127) { check_digit = 0; }
concat(dest, TeleTable[check_digit]);
/* Stop character */
concat(dest, TeleTable['z']);
expand(symbol, dest);
ustrcpy(symbol->text, temp);
return error_number;
}

800
backend/upcean.c Normal file
View file

@ -0,0 +1,800 @@
/* upcean.c - Handles UPC, EAN and ISBN
libzint - the open source barcode library
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define SODIUM "0123456789+"
#define EAN2 102
#define EAN5 105
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "common.h"
/* UPC and EAN tables checked against EN 797:1996 */
static char *UPCParity0[10] = {"BBBAAA", "BBABAA", "BBAABA", "BBAAAB", "BABBAA", "BAABBA", "BAAABB",
"BABABA", "BABAAB", "BAABAB"}; /* Number set for UPC-E symbol (EN Table 4) */
static char *UPCParity1[10] = {"AAABBB", "AABABB", "AABBAB", "AABBBA", "ABAABB", "ABBAAB", "ABBBAA",
"ABABAB", "ABABBA", "ABBABA"}; /* Not covered by BS EN 797:1995 */
static char *EAN2Parity[4] = {"AA", "AB", "BA", "BB"}; /* Number sets for 2-digit add-on (EN Table 6) */
static char *EAN5Parity[10] = {"BBAAA", "BABAA", "BAABA", "BAAAB", "ABBAA", "AABBA", "AAABB", "ABABA",
"ABAAB", "AABAB"}; /* Number set for 5-digit add-on (EN Table 7) */
static char *EAN13Parity[10] = {"AAAAA", "ABABB", "ABBAB", "ABBBA", "BAABB", "BBAAB", "BBBAA", "BABAB",
"BABBA", "BBABA"}; /* Left hand of the EAN-13 symbol (EN Table 3) */
static char *EANsetA[10] = {"3211", "2221", "2122", "1411", "1132", "1231", "1114", "1312", "1213",
"3112"}; /* Representation set A and C (EN Table 1) */
static char *EANsetB[10] = {"1123", "1222", "2212", "1141", "2311", "1321", "4111", "2131", "3121",
"2113"}; /* Representation set B (EN Table 1) */
char upc_check(char source[])
{ /* Calculate the correct check digit for a UPC barcode */
unsigned int i, count, check_digit;
count = 0;
for (i = 0; i < strlen(source); i++)
{
count += ctoi(source[i]);
if ((i%2) == 0)
{
count += 2 * (ctoi(source[i]));
}
}
check_digit = 10 - (count%10);
if (check_digit == 10) { check_digit = 0; }
return itoc(check_digit);
}
void upca_draw(char source[], char dest[])
{ /* UPC A is usually used for 12 digit numbers, but this function takes a source of any length */
unsigned int i, half_way;
half_way = strlen(source) / 2;
/* start character */
concat (dest, "111");
for(i = 0; i <= strlen(source); i++)
{
if (i == half_way)
{
/* middle character - separates manufacturer no. from product no. */
/* also inverts right hand characters */
concat(dest, "11111");
}
lookup(NEON, EANsetA, source[i], dest);
}
/* stop character */
concat (dest, "111");
}
void upca(struct zint_symbol *symbol, unsigned char source[], char dest[])
{ /* Make a UPC A barcode when we haven't been given the check digit */
int length;
char gtin[15];
strcpy(gtin, (char*)source);
length = strlen(gtin);
gtin[length] = upc_check(gtin);
gtin[length + 1] = '\0';
upca_draw(gtin, dest);
ustrcpy(symbol->text, (unsigned char*)gtin);
}
void upce(struct zint_symbol *symbol, unsigned char source[], char dest[])
{ /* UPC E is a zero-compressed version of UPC A */
unsigned int i, num_system;
char emode, equivalent[12], check_digit, parity[8], temp[8];
char hrt[9];
/* Two number systems can be used - system 0 and system 1 */
if(ustrlen(source) == 7) {
switch(source[0]) {
case '0': num_system = 0; break;
case '1': num_system = 1; break;
default: num_system = 0; source[0] = '0'; break;
}
strcpy(temp, (char*)source);
strcpy(hrt, (char*)source);
for(i = 1; i <= 7; i++) {
source[i - 1] = temp[i];
}
}
else {
num_system = 0;
hrt[0] = '0';
hrt[1] = '\0';
concat(hrt, (char*)source);
}
/* Expand the zero-compressed UPCE code to make a UPCA equivalent (EN Table 5) */
emode = source[5];
for(i = 0; i < 11; i++) {
equivalent[i] = '0';
}
if(num_system == 1) { equivalent[0] = temp[0]; }
equivalent[1] = source[0];
equivalent[2] = source[1];
equivalent[11] = '\0';
switch(emode)
{
case '0':
case '1':
case '2':
equivalent[3] = emode;
equivalent[8] = source[2];
equivalent[9] = source[3];
equivalent[10] = source[4];
break;
case '3':
equivalent[3] = source[2];
equivalent[9] = source[3];
equivalent[10] = source[4];
if(((source[2] == '0') || (source[2] == '1')) || (source[2] == '2')) {
/* Note 1 - "X3 shall not be equal to 0, 1 or 2" */
strcpy(symbol->errtxt, "Invalid UPC-E data");
}
break;
case '4':
equivalent[3] = source[2];
equivalent[4] = source[3];
equivalent[10] = source[4];
if(source[3] == '0') {
/* Note 2 - "X4 shall not be equal to 0" */
strcpy(symbol->errtxt, "Invalid UPC-E data");
}
break;
case '5':
case '6':
case '7':
case '8':
case '9':
equivalent[3] = source[2];
equivalent[4] = source[3];
equivalent[5] = source[4];
equivalent[10] = emode;
if(source[4] == '0') {
/* Note 3 - "X5 shall not be equal to 0" */
strcpy(symbol->errtxt, "Invalid UPC-E data");
}
break;
}
/* Get the check digit from the expanded UPCA code */
check_digit = upc_check(equivalent);
/* Use the number system and check digit information to choose a parity scheme */
if(num_system == 1) {
strcpy(parity, UPCParity1[ctoi(check_digit)]);
} else {
strcpy(parity, UPCParity0[ctoi(check_digit)]);
}
/* Take all this information and make the barcode pattern */
/* start character */
concat (dest, "111");
for(i = 0; i <= ustrlen(source); i++) {
switch(parity[i]) {
case 'A': lookup(NEON, EANsetA, source[i], dest); break;
case 'B': lookup(NEON, EANsetB, source[i], dest); break;
}
}
/* stop character */
concat (dest, "111111");
hrt[7] = check_digit;
hrt[8] = '\0';
ustrcpy(symbol->text, (unsigned char*)hrt);
}
void add_on(unsigned char source[], char dest[], int mode)
{ /* EAN-2 and EAN-5 add-on codes */
char parity[6];
unsigned int i, code_type;
/* If an add-on then append with space */
if (mode != 0)
{
concat(dest, "9");
}
/* Start character */
concat (dest, "112");
/* Determine EAN2 or EAN5 add-on */
if(ustrlen(source) == 2)
{
code_type = EAN2;
}
else
{
code_type = EAN5;
}
/* Calculate parity for EAN2 */
if(code_type == EAN2)
{
int code_value, parity_bit;
code_value = (10 * ctoi(source[0])) + ctoi(source[1]);
parity_bit = code_value%4;
strcpy(parity, EAN2Parity[parity_bit]);
}
if(code_type == EAN5)
{
int values[6], parity_sum, parity_bit;
for(i = 0; i < 6; i++)
{
values[i] = ctoi(source[i]);
}
parity_sum = (3 * (values[0] + values[2] + values[4]));
parity_sum += (9 * (values[1] + values[3]));
parity_bit = parity_sum%10;
strcpy(parity, EAN5Parity[parity_bit]);
}
for(i = 0; i < ustrlen(source); i++)
{
switch(parity[i]) {
case 'A': lookup(NEON, EANsetA, source[i], dest); break;
case 'B': lookup(NEON, EANsetB, source[i], dest); break;
}
/* Glyph separator */
if(i != (ustrlen(source) - 1))
{
concat (dest, "11");
}
}
}
/* ************************ EAN-13 ****************** */
char ean_check(char source[])
{ /* Calculate the correct check digit for a EAN-13 barcode */
int i;
unsigned int h, count, check_digit;
count = 0;
h = strlen(source);
for (i = h - 1; i >= 0; i--)
{
count += ctoi(source[i]);
if (!((i%2) == 0))
{
count += 2 * ctoi(source[i]);
}
}
check_digit = 10 - (count%10);
if (check_digit == 10) { check_digit = 0; }
return itoc(check_digit);
}
void ean13(struct zint_symbol *symbol, unsigned char source[], char dest[])
{
unsigned int length, i, half_way;
char parity[6];
char gtin[15];
strcpy(parity, "");
strcpy(gtin, (char*)source);
/* Add the appropriate check digit */
length = strlen(gtin);
gtin[length] = ean_check(gtin);
gtin[length + 1] = '\0';
/* Get parity for first half of the symbol */
lookup(SODIUM, EAN13Parity, gtin[0], parity);
/* Now get on with the cipher */
half_way = 7;
/* start character */
concat (dest, "111");
length = strlen(gtin);
for(i = 1; i <= length; i++)
{
if (i == half_way)
{
/* middle character - separates manufacturer no. from product no. */
/* also inverses right hand characters */
concat (dest, "11111");
}
if(((i > 1) && (i < 7)) && (parity[i - 2] == 'B'))
{
lookup(NEON, EANsetB, gtin[i], dest);
}
else
{
lookup(NEON, EANsetA, gtin[i], dest);
}
}
/* stop character */
concat (dest, "111");
ustrcpy(symbol->text, (unsigned char*)gtin);
}
void ean8(struct zint_symbol *symbol, unsigned char source[], char dest[])
{ /* Make an EAN-8 barcode when we haven't been given the check digit */
/* EAN-8 is basically the same as UPC-A but with fewer digits */
int length;
char gtin[10];
strcpy(gtin, (char*)source);
length = strlen(gtin);
gtin[length] = upc_check(gtin);
gtin[length + 1] = '\0';
upca_draw(gtin, dest);
ustrcpy(symbol->text, (unsigned char*)gtin);
}
char isbn13_check(unsigned char source[]) /* For ISBN(13) only */
{
unsigned int i, weight, sum, check, h;
sum = 0;
weight = 1;
h = ustrlen(source) - 1;
for(i = 0; i < h; i++)
{
sum += ctoi(source[i]) * weight;
if(weight == 1) weight = 3; else weight = 1;
}
check = sum % 10;
check = 10 - check;
return itoc(check);
}
char isbn_check(unsigned char source[]) /* For ISBN(10) and SBN only */
{
unsigned int i, weight, sum, check, h;
char check_char;
sum = 0;
weight = 1;
h = ustrlen(source) - 1;
for(i = 0; i < h; i++)
{
sum += ctoi(source[i]) * weight;
weight++;
}
check = sum % 11;
check_char = itoc(check);
if(check == 10) { check_char = 'X'; }
return check_char;
}
int isbn(struct zint_symbol *symbol, unsigned char source[], const unsigned int src_len, char dest[]) /* Make an EAN-13 barcode from an SBN or ISBN */
{
int i, error_number;
char check_digit;
to_upper(source);
error_number = is_sane("0123456789X", source, src_len);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in input");
return error_number;
}
/* Input must be 9, 10 or 13 characters */
if(((src_len < 9) || (src_len > 13)) || ((src_len > 10) && (src_len < 13)))
{
strcpy(symbol->errtxt, "Input wrong length");
return ERROR_TOO_LONG;
}
if(src_len == 13) /* Using 13 character ISBN */
{
if(!(((source[0] == '9') && (source[1] == '7')) &&
((source[2] == '8') || (source[2] == '9'))))
{
strcpy(symbol->errtxt, "Invalid ISBN");
return ERROR_INVALID_DATA;
}
check_digit = isbn13_check(source);
if (source[src_len - 1] != check_digit)
{
strcpy(symbol->errtxt, "Incorrect ISBN check");
return ERROR_INVALID_CHECK;
}
source[12] = '\0';
ean13(symbol, source, dest);
}
if(src_len == 10) /* Using 10 digit ISBN */
{
check_digit = isbn_check(source);
if(check_digit != source[src_len - 1])
{
strcpy(symbol->errtxt, "Incorrect ISBN check");
return ERROR_INVALID_CHECK;
}
for(i = 13; i > 0; i--)
{
source[i] = source[i - 3];
}
source[0] = '9';
source[1] = '7';
source[2] = '8';
source[12] = '\0';
ean13(symbol, source, dest);
}
if(src_len == 9) /* Using 9 digit SBN */
{
/* Add leading zero */
for(i = 10; i > 0; i--)
{
source[i] = source[i - 1];
}
source[0] = '0';
/* Verify check digit */
check_digit = isbn_check(source);
if(check_digit != source[ustrlen(source) - 1])
{
strcpy(symbol->errtxt, "Incorrect SBN check");
return ERROR_INVALID_CHECK;
}
/* Convert to EAN-13 number */
for(i = 13; i > 0; i--)
{
source[i] = source[i - 3];
}
source[0] = '9';
source[1] = '7';
source[2] = '8';
source[12] = '\0';
ean13(symbol, source, dest);
}
return 0;
}
void ean_leading_zeroes(struct zint_symbol *symbol, unsigned char source[], unsigned char local_source[]) {
/* Add leading zeroes to EAN and UPC strings */
unsigned char first_part[20], second_part[20], zfirst_part[20], zsecond_part[20];
int with_addon = 0;
int first_len = 0, second_len = 0, zfirst_len = 0, zsecond_len = 0, i, h;
h = ustrlen(source);
for(i = 0; i < h; i++) {
if(source[i] == '+') {
with_addon = 1;
} else {
if(with_addon == 0) {
first_len++;
} else {
second_len++;
}
}
}
ustrcpy(first_part, (unsigned char *)"");
ustrcpy(second_part, (unsigned char *)"");
ustrcpy(zfirst_part, (unsigned char *)"");
ustrcpy(zsecond_part, (unsigned char *)"");
/* Split input into two strings */
for(i = 0; i < first_len; i++) {
first_part[i] = source[i];
first_part[i + 1] = '\0';
}
for(i = 0; i < second_len; i++) {
second_part[i] = source[i + first_len + 1];
second_part[i + 1] = '\0';
}
/* Calculate target lengths */
if(second_len <= 5) { zsecond_len = 5; }
if(second_len <= 2) { zsecond_len = 2; }
if(second_len == 0) { zsecond_len = 0; }
switch(symbol->symbology) {
case BARCODE_EANX:
case BARCODE_EANX_CC:
if(first_len <= 12) { zfirst_len = 12; }
if(first_len <= 7) { zfirst_len = 7; }
if(second_len == 0) {
if(first_len <= 5) { zfirst_len = 5; }
if(first_len <= 2) { zfirst_len = 2; }
}
break;
case BARCODE_UPCA:
case BARCODE_UPCA_CC:
zfirst_len = 11;
break;
case BARCODE_UPCE:
case BARCODE_UPCE_CC:
if(first_len == 7) { zfirst_len = 7; }
if(first_len <= 6) { zfirst_len = 6; }
break;
case BARCODE_ISBNX:
if(first_len <= 9) { zfirst_len = 9; }
break;
}
/* Add leading zeroes */
for(i = 0; i < (zfirst_len - first_len); i++) {
uconcat(zfirst_part, (unsigned char *)"0");
}
uconcat(zfirst_part, first_part);
for(i = 0; i < (zsecond_len - second_len); i++) {
uconcat(zsecond_part, (unsigned char *)"0");
}
uconcat(zsecond_part, second_part);
/* Copy adjusted data back to local_source */
uconcat(local_source, zfirst_part);
if(zsecond_len != 0) {
uconcat(local_source, (unsigned char *)"+");
uconcat(local_source, zsecond_part);
}
}
int eanx(struct zint_symbol *symbol, unsigned char source[], int src_len)
{
/* splits string to parts before and after '+' parts */
unsigned char first_part[20] = { 0 }, second_part[20] = { 0 }, dest[1000] = { 0 };
unsigned char local_source[20] = { 0 };
unsigned int latch, reader, writer, with_addon;
int error_number, i;
with_addon = FALSE;
latch = FALSE;
writer = 0;
if(src_len > 19) {
strcpy(symbol->errtxt, "Input too long");
return ERROR_TOO_LONG;
}
if(symbol->symbology != BARCODE_ISBNX) {
/* ISBN has it's own checking routine */
error_number = is_sane("0123456789+", source, src_len);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in data");
return error_number;
}
} else {
error_number = is_sane("0123456789Xx", source, src_len);
if(error_number == ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "Invalid characters in input");
return error_number;
}
}
/* Add leading zeroes */
ustrcpy(local_source, (unsigned char *)"");
if(symbol->symbology == BARCODE_ISBNX) {
to_upper(local_source);
}
ean_leading_zeroes(symbol, source, local_source);
for(reader = 0; reader <= ustrlen(local_source); reader++)
{
if(source[reader] == '+') { with_addon = TRUE; }
}
reader = 0;
if(with_addon) {
do {
if(local_source[reader] == '+') {
first_part[writer] = '\0';
latch = TRUE;
reader++;
writer = 0;
}
if(latch) {
second_part[writer] = local_source[reader];
reader++;
writer++;
} else {
first_part[writer] = local_source[reader];
reader++;
writer++;
}
} while (reader <= ustrlen(local_source));
} else {
strcpy((char*)first_part, (char*)local_source);
}
switch(symbol->symbology)
{
case BARCODE_EANX:
switch(ustrlen(first_part))
{
case 2: add_on(first_part, (char*)dest, 0); ustrcpy(symbol->text, first_part); break;
case 5: add_on(first_part, (char*)dest, 0); ustrcpy(symbol->text, first_part); break;
case 7: ean8(symbol, first_part, (char*)dest); break;
case 12: ean13(symbol, first_part, (char*)dest); break;
default: strcpy(symbol->errtxt, "Invalid length input"); return ERROR_TOO_LONG; break;
}
break;
case BARCODE_EANX_CC:
switch(ustrlen(first_part))
{ /* Adds vertical separator bars according to ISO/IEC 24723 section 11.4 */
case 7: set_module(symbol, symbol->rows, 1);
set_module(symbol, symbol->rows, 67);
set_module(symbol, symbol->rows + 1, 0);
set_module(symbol, symbol->rows + 1, 68);
set_module(symbol, symbol->rows + 2, 1);
set_module(symbol, symbol->rows + 1, 67);
symbol->row_height[symbol->rows] = 2;
symbol->row_height[symbol->rows + 1] = 2;
symbol->row_height[symbol->rows + 2] = 2;
symbol->rows += 3;
ean8(symbol, first_part, (char*)dest); break;
case 12:set_module(symbol, symbol->rows, 1);
set_module(symbol, symbol->rows, 95);
set_module(symbol, symbol->rows + 1, 0);
set_module(symbol, symbol->rows + 1, 96);
set_module(symbol, symbol->rows + 2, 1);
set_module(symbol, symbol->rows + 2, 95);
symbol->row_height[symbol->rows] = 2;
symbol->row_height[symbol->rows + 1] = 2;
symbol->row_height[symbol->rows + 2] = 2;
symbol->rows += 3;
ean13(symbol, first_part, (char*)dest); break;
default: strcpy(symbol->errtxt, "Invalid length EAN input"); return ERROR_TOO_LONG; break;
}
break;
case BARCODE_UPCA:
if(ustrlen(first_part) == 11) {
upca(symbol, first_part, (char*)dest);
} else {
strcpy(symbol->errtxt, "Input wrong length");
return ERROR_TOO_LONG;
}
break;
case BARCODE_UPCA_CC:
if(ustrlen(first_part) == 11) {
set_module(symbol, symbol->rows, 1);
set_module(symbol, symbol->rows, 95);
set_module(symbol, symbol->rows + 1, 0);
set_module(symbol, symbol->rows + 1, 96);
set_module(symbol, symbol->rows + 2, 1);
set_module(symbol, symbol->rows + 2, 95);
symbol->row_height[symbol->rows] = 2;
symbol->row_height[symbol->rows + 1] = 2;
symbol->row_height[symbol->rows + 2] = 2;
symbol->rows += 3;
upca(symbol, first_part, (char*)dest);
} else {
strcpy(symbol->errtxt, "UPCA input wrong length");
return ERROR_TOO_LONG;
}
break;
case BARCODE_UPCE:
if((ustrlen(first_part) >= 6) && (ustrlen(first_part) <= 7)) {
upce(symbol, first_part, (char*)dest);
} else {
strcpy(symbol->errtxt, "Input wrong length");
return ERROR_TOO_LONG;
}
break;
case BARCODE_UPCE_CC:
if((ustrlen(first_part) >= 6) && (ustrlen(first_part) <= 7)) {
set_module(symbol, symbol->rows, 1);
set_module(symbol, symbol->rows, 51);
set_module(symbol, symbol->rows + 1, 0);
set_module(symbol, symbol->rows + 1, 52);
set_module(symbol, symbol->rows + 2, 1);
set_module(symbol, symbol->rows + 2, 51);
symbol->row_height[symbol->rows] = 2;
symbol->row_height[symbol->rows + 1] = 2;
symbol->row_height[symbol->rows + 2] = 2;
symbol->rows += 3;
upce(symbol, first_part, (char*)dest);
} else {
strcpy(symbol->errtxt, "UPCE input wrong length");
return ERROR_TOO_LONG;
}
break;
case BARCODE_ISBNX:
error_number = isbn(symbol, first_part, ustrlen(first_part), (char*)dest);
if(error_number > 4) {
return error_number;
}
break;
}
switch(ustrlen(second_part))
{
case 0: break;
case 2:
add_on(second_part, (char*)dest, 1);
uconcat(symbol->text, (unsigned char*)"+");
uconcat(symbol->text, second_part);
break;
case 5:
add_on(second_part, (char*)dest, 1);
uconcat(symbol->text, (unsigned char*)"+");
uconcat(symbol->text, second_part);
break;
default:
strcpy(symbol->errtxt, "Invalid length input");
return ERROR_TOO_LONG;
break;
}
expand(symbol, (char*)dest);
switch(symbol->symbology) {
case BARCODE_EANX_CC:
case BARCODE_UPCA_CC:
case BARCODE_UPCE_CC:
/* shift the symbol to the right one space to allow for separator bars */
for(i = (symbol->width + 1); i >= 1; i--) {
if(module_is_set(symbol, symbol->rows - 1, i - 1)) {
set_module(symbol, symbol->rows - 1, i);
} else {
unset_module(symbol, symbol->rows - 1, i);
}
}
unset_module(symbol, symbol->rows - 1, 0);
symbol->width += 2;
break;
}
if((symbol->errtxt[0] == 'w') && (error_number == 0)) {
error_number = 1; /* flag UPC-E warnings */
}
return error_number;
}

206
backend/zint.h Normal file
View file

@ -0,0 +1,206 @@
/* zint.h - definitions for libzint
libzint - the open source barcode library
Copyright (C) 2009 Robin Stuart <robin@zint.org.uk>
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 3 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef ZINT_H
#define ZINT_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct zint_symbol {
int symbology;
int height;
int whitespace_width;
int border_width;
int output_options;
char fgcolour[10];
char bgcolour[10];
char outfile[256];
float scale;
int option_1;
int option_2;
int option_3;
int show_hrt;
int input_mode;
unsigned char text[128];
int rows;
int width;
char primary[128];
unsigned char encoded_data[178][143];
int row_height[178]; /* Largest symbol is 177x177 QR Code */
char errtxt[100];
char *bitmap;
int bitmap_width;
int bitmap_height;
};
/* Tbarcode 7 codes */
#define BARCODE_CODE11 1
#define BARCODE_C25MATRIX 2
#define BARCODE_C25INTER 3
#define BARCODE_C25IATA 4
#define BARCODE_C25LOGIC 6
#define BARCODE_C25IND 7
#define BARCODE_CODE39 8
#define BARCODE_EXCODE39 9
#define BARCODE_EANX 13
#define BARCODE_EAN128 16
#define BARCODE_CODABAR 18
#define BARCODE_CODE128 20
#define BARCODE_DPLEIT 21
#define BARCODE_DPIDENT 22
#define BARCODE_CODE16K 23
#define BARCODE_CODE49 24
#define BARCODE_CODE93 25
#define BARCODE_FLAT 28
#define BARCODE_RSS14 29
#define BARCODE_RSS_LTD 30
#define BARCODE_RSS_EXP 31
#define BARCODE_TELEPEN 32
#define BARCODE_UPCA 34
#define BARCODE_UPCE 37
#define BARCODE_POSTNET 40
#define BARCODE_MSI_PLESSEY 47
#define BARCODE_FIM 49
#define BARCODE_LOGMARS 50
#define BARCODE_PHARMA 51
#define BARCODE_PZN 52
#define BARCODE_PHARMA_TWO 53
#define BARCODE_PDF417 55
#define BARCODE_PDF417TRUNC 56
#define BARCODE_MAXICODE 57
#define BARCODE_QRCODE 58
#define BARCODE_CODE128B 60
#define BARCODE_AUSPOST 63
#define BARCODE_AUSREPLY 66
#define BARCODE_AUSROUTE 67
#define BARCODE_AUSREDIRECT 68
#define BARCODE_ISBNX 69
#define BARCODE_RM4SCC 70
#define BARCODE_DATAMATRIX 71
#define BARCODE_EAN14 72
#define BARCODE_CODABLOCKF 74
#define BARCODE_NVE18 75
#define BARCODE_JAPANPOST 76
#define BARCODE_KOREAPOST 77
#define BARCODE_RSS14STACK 79
#define BARCODE_RSS14STACK_OMNI 80
#define BARCODE_RSS_EXPSTACK 81
#define BARCODE_PLANET 82
#define BARCODE_MICROPDF417 84
#define BARCODE_ONECODE 85
#define BARCODE_PLESSEY 86
/* Tbarcode 8 codes */
#define BARCODE_TELEPEN_NUM 87
#define BARCODE_ITF14 89
#define BARCODE_KIX 90
#define BARCODE_AZTEC 92
#define BARCODE_DAFT 93
#define BARCODE_MICROQR 97
/* Tbarcode 9 codes */
#define BARCODE_HIBC_128 98
#define BARCODE_HIBC_39 99
#define BARCODE_HIBC_DM 102
#define BARCODE_HIBC_QR 104
#define BARCODE_HIBC_PDF 106
#define BARCODE_HIBC_MICPDF 108
#define BARCODE_HIBC_BLOCKF 110
#define BARCODE_HIBC_AZTEC 112
/* Zint specific */
#define BARCODE_AZRUNE 128
#define BARCODE_CODE32 129
#define BARCODE_EANX_CC 130
#define BARCODE_EAN128_CC 131
#define BARCODE_RSS14_CC 132
#define BARCODE_RSS_LTD_CC 133
#define BARCODE_RSS_EXP_CC 134
#define BARCODE_UPCA_CC 135
#define BARCODE_UPCE_CC 136
#define BARCODE_RSS14STACK_CC 137
#define BARCODE_RSS14_OMNI_CC 138
#define BARCODE_RSS_EXPSTACK_CC 139
#define BARCODE_CHANNEL 140
#define BARCODE_CODEONE 141
#define BARCODE_GRIDMATRIX 142
#define BARCODE_NO_ASCII 1
#define BARCODE_BIND 2
#define BARCODE_BOX 4
#define BARCODE_STDOUT 8
#define READER_INIT 16
#define DATA_MODE 0
#define UNICODE_MODE 1
#define GS1_MODE 2
#define KANJI_MODE 3
#define SJIS_MODE 4
#define DM_SQUARE 100
#define WARN_INVALID_OPTION 2
#define ERROR_TOO_LONG 5
#define ERROR_INVALID_DATA 6
#define ERROR_INVALID_CHECK 7
#define ERROR_INVALID_OPTION 8
#define ERROR_ENCODING_PROBLEM 9
#define ERROR_FILE_ACCESS 10
#define ERROR_MEMORY 11
#if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_MSC_VER)
# if defined (DLL_EXPORT) || defined(PIC) || defined(_USRDLL)
# define ZINT_EXTERN __declspec(dllexport)
# elif defined(ZINT_DLL)
# define ZINT_EXTERN __declspec(dllimport)
# else
# define ZINT_EXTERN extern
# endif
#else
# define ZINT_EXTERN extern
#endif
ZINT_EXTERN struct zint_symbol *ZBarcode_Create(void);
ZINT_EXTERN void ZBarcode_Clear(struct zint_symbol *symbol);
ZINT_EXTERN void ZBarcode_Delete(struct zint_symbol *symbol);
ZINT_EXTERN int ZBarcode_Encode(struct zint_symbol *symbol, unsigned char *input, int length);
ZINT_EXTERN int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename);
ZINT_EXTERN int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle);
ZINT_EXTERN int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, unsigned char *input, int length, int rotate_angle);
ZINT_EXTERN int ZBarcode_Encode_File_and_Print(struct zint_symbol *symbol, char *filename, int rotate_angle);
ZINT_EXTERN int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle);
ZINT_EXTERN int ZBarcode_Encode_and_Buffer(struct zint_symbol *symbol, unsigned char *input, int length, int rotate_angle);
ZINT_EXTERN int ZBarcode_Encode_File_and_Buffer(struct zint_symbol *symbol, char *filename, int rotate_angle);
ZINT_EXTERN int ZBarcode_ValidID(int symbol_id);
/* Depreciated */
ZINT_EXTERN int ZBarcode_Print_Rotated(struct zint_symbol *symbol, int rotate_angle);
ZINT_EXTERN int ZBarcode_Encode_and_Print_Rotated(struct zint_symbol *symbol, unsigned char *input, int rotate_angle);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* ZINT_H */