2008-09-03 00:01:41 +04:00
/* aztec.c - Handles Aztec 2D Symbols */
/*
libzint - the open source barcode library
2009-06-19 22:29:49 +04:00
Copyright ( C ) 2009 Robin Stuart < robin @ zint . org . uk >
2008-09-03 00:01:41 +04:00
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>
2008-11-08 02:42:53 +03:00
# include <stdlib.h>
2009-06-03 00:23:38 +04:00
# ifdef _MSC_VER
2009-06-18 14:20:23 +04:00
# include <malloc.h>
2009-06-03 00:23:38 +04:00
# endif
2008-09-03 00:01:41 +04:00
# include "common.h"
# include "aztec.h"
# include "reedsol.h"
2012-12-29 22:37:03 +04:00
/**
* Shorten the string by one character
*/
2008-09-03 00:01:41 +04:00
void mapshorten ( int * charmap , int * typemap , int start , int length )
2012-12-29 22:37:03 +04:00
{
2009-10-06 23:03:00 +04:00
memmove ( charmap + start + 1 , charmap + start + 2 , ( length - 1 ) * sizeof ( int ) ) ;
memmove ( typemap + start + 1 , typemap + start + 2 , ( length - 1 ) * sizeof ( int ) ) ;
2008-09-03 00:01:41 +04:00
}
2012-12-29 22:37:03 +04:00
/**
* Insert a character into the middle of a string at position posn
*/
2008-09-03 00:01:41 +04:00
void insert ( char binary_string [ ] , int posn , char newbit )
2012-12-29 22:37:03 +04:00
{
2008-09-03 00:01:41 +04:00
int i , end ;
end = strlen ( binary_string ) ;
for ( i = end ; i > posn ; i - - ) {
binary_string [ i ] = binary_string [ i - 1 ] ;
}
binary_string [ posn ] = newbit ;
}
2012-12-29 22:37:03 +04:00
/**
* Encode input data into a binary string
*/
2009-10-06 23:03:00 +04:00
int aztec_text_process ( unsigned char source [ ] , const unsigned int src_len , char binary_string [ ] , int gs1 )
2012-12-29 22:37:03 +04:00
{
2008-09-30 19:05:53 +04:00
int i , j , k , bytes ;
2009-06-03 00:23:38 +04:00
int curtable , newtable , lasttable , chartype , maplength , blocks , debug ;
# ifndef _MSC_VER
2009-10-06 23:03:00 +04:00
int charmap [ src_len * 2 ] , typemap [ src_len * 2 ] ;
int blockmap [ 2 ] [ src_len ] ;
2009-06-03 00:23:38 +04:00
# else
2009-10-06 23:03:00 +04:00
int * charmap = ( int * ) _alloca ( src_len * 2 * sizeof ( int ) ) ;
int * typemap = ( int * ) _alloca ( src_len * 2 * sizeof ( int ) ) ;
2009-06-03 00:23:38 +04:00
int * blockmap [ 2 ] ;
2009-10-06 23:03:00 +04:00
blockmap [ 0 ] = ( int * ) _alloca ( src_len * sizeof ( int ) ) ;
blockmap [ 1 ] = ( int * ) _alloca ( src_len * sizeof ( int ) ) ;
2009-06-03 00:23:38 +04:00
# endif
2008-09-03 00:01:41 +04:00
/* Lookup input string in encoding table */
2009-01-16 08:50:22 +03:00
maplength = 0 ;
2009-01-24 17:35:46 +03:00
debug = 0 ;
2009-10-06 23:03:00 +04:00
for ( i = 0 ; i < src_len ; i + + ) {
2009-01-24 17:35:46 +03:00
if ( gs1 & & ( i = = 0 ) ) {
/* Add FNC1 to beginning of GS1 messages */
charmap [ maplength ] = 0 ;
2009-10-06 23:03:00 +04:00
typemap [ maplength + + ] = PUNC ;
2009-01-24 17:35:46 +03:00
charmap [ maplength ] = 400 ;
2009-10-06 23:03:00 +04:00
typemap [ maplength + + ] = PUNC ;
2009-01-24 17:35:46 +03:00
}
2009-01-16 08:50:22 +03:00
if ( ( gs1 ) & & ( source [ i ] = = ' [ ' ) ) {
/* FNC1 represented by FLG(0) */
charmap [ maplength ] = 0 ;
2009-10-06 23:03:00 +04:00
typemap [ maplength + + ] = PUNC ;
2009-01-16 08:50:22 +03:00
charmap [ maplength ] = 400 ;
2009-10-06 23:03:00 +04:00
typemap [ maplength + + ] = PUNC ;
2009-08-05 21:59:28 +04:00
} else {
if ( source [ i ] > 127 ) {
charmap [ maplength ] = source [ i ] ;
2009-10-06 23:03:00 +04:00
typemap [ maplength + + ] = BINARY ;
2009-08-05 21:59:28 +04:00
} else {
charmap [ maplength ] = AztecSymbolChar [ source [ i ] ] ;
2009-10-06 23:03:00 +04:00
typemap [ maplength + + ] = AztecCodeSet [ source [ i ] ] ;
2009-08-05 21:59:28 +04:00
}
2009-01-16 08:50:22 +03:00
}
2008-09-03 00:01:41 +04:00
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
/* Look for double character encoding possibilities */
i = 0 ;
do {
if ( ( ( charmap [ i ] = = 300 ) & & ( charmap [ i + 1 ] = = 11 ) ) & & ( ( typemap [ i ] = = PUNC ) & & ( typemap [ i + 1 ] = = PUNC ) ) ) {
/* CR LF combination */
charmap [ i ] = 2 ;
typemap [ i ] = PUNC ;
mapshorten ( charmap , typemap , i , maplength ) ;
maplength - - ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
if ( ( ( charmap [ i ] = = 302 ) & & ( charmap [ i + 1 ] = = 1 ) ) & & ( ( typemap [ i ] = = 24 ) & & ( typemap [ i + 1 ] = = 23 ) ) ) {
/* . SP combination */
charmap [ i ] = 3 ;
typemap [ i ] = PUNC ;
mapshorten ( charmap , typemap , i , maplength ) ;
maplength - - ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
if ( ( ( charmap [ i ] = = 301 ) & & ( charmap [ i + 1 ] = = 1 ) ) & & ( ( typemap [ i ] = = 24 ) & & ( typemap [ i + 1 ] = = 23 ) ) ) {
/* , SP combination */
charmap [ i ] = 4 ;
typemap [ i ] = PUNC ;
mapshorten ( charmap , typemap , i , maplength ) ;
maplength - - ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
if ( ( ( charmap [ i ] = = 21 ) & & ( charmap [ i + 1 ] = = 1 ) ) & & ( ( typemap [ i ] = = PUNC ) & & ( typemap [ i + 1 ] = = 23 ) ) ) {
/* : SP combination */
charmap [ i ] = 5 ;
typemap [ i ] = PUNC ;
mapshorten ( charmap , typemap , i , maplength ) ;
maplength - - ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
i + + ;
2008-10-06 20:27:48 +04:00
} while ( i < ( maplength - 1 ) ) ;
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
/* look for blocks of characters which use the same table */
2010-04-06 13:14:28 +04:00
blocks = 1 ;
2008-09-03 00:01:41 +04:00
blockmap [ 0 ] [ 0 ] = typemap [ 0 ] ;
blockmap [ 1 ] [ 0 ] = 1 ;
for ( i = 1 ; i < maplength ; i + + ) {
if ( typemap [ i ] = = typemap [ i - 1 ] ) {
2010-04-06 13:14:28 +04:00
blockmap [ 1 ] [ blocks - 1 ] + + ;
2008-09-03 00:01:41 +04:00
} else {
blocks + + ;
2010-04-06 13:14:28 +04:00
blockmap [ 0 ] [ blocks - 1 ] = typemap [ i ] ;
blockmap [ 1 ] [ blocks - 1 ] = 1 ;
2008-09-03 00:01:41 +04:00
}
}
if ( blockmap [ 0 ] [ 0 ] & 1 ) { blockmap [ 0 ] [ 0 ] = 1 ; }
if ( blockmap [ 0 ] [ 0 ] & 2 ) { blockmap [ 0 ] [ 0 ] = 2 ; }
if ( blockmap [ 0 ] [ 0 ] & 4 ) { blockmap [ 0 ] [ 0 ] = 4 ; }
if ( blockmap [ 0 ] [ 0 ] & 8 ) { blockmap [ 0 ] [ 0 ] = 8 ; }
2008-10-08 19:15:49 +04:00
if ( blocks > 1 ) {
/* look for adjacent blocks which can use the same table (left to right search) */
for ( i = 1 ; i < blocks ; i + + ) {
if ( blockmap [ 0 ] [ i ] & blockmap [ 0 ] [ i - 1 ] ) {
blockmap [ 0 ] [ i ] = ( blockmap [ 0 ] [ i ] & blockmap [ 0 ] [ i - 1 ] ) ;
}
2008-09-03 00:01:41 +04:00
}
2008-10-08 19:15:49 +04:00
if ( blockmap [ 0 ] [ blocks - 1 ] & 1 ) { blockmap [ 0 ] [ blocks - 1 ] = 1 ; }
if ( blockmap [ 0 ] [ blocks - 1 ] & 2 ) { blockmap [ 0 ] [ blocks - 1 ] = 2 ; }
if ( blockmap [ 0 ] [ blocks - 1 ] & 4 ) { blockmap [ 0 ] [ blocks - 1 ] = 4 ; }
if ( blockmap [ 0 ] [ blocks - 1 ] & 8 ) { blockmap [ 0 ] [ blocks - 1 ] = 8 ; }
/* look for adjacent blocks which can use the same table (right to left search) */
for ( i = blocks - 1 ; i > 0 ; i - - ) {
if ( blockmap [ 0 ] [ i ] & blockmap [ 0 ] [ i + 1 ] ) {
blockmap [ 0 ] [ i ] = ( blockmap [ 0 ] [ i ] & blockmap [ 0 ] [ i + 1 ] ) ;
2008-09-03 00:01:41 +04:00
}
}
2008-10-08 19:15:49 +04:00
/* determine the encoding table for characters which do not fit with adjacent blocks */
for ( i = 1 ; i < blocks ; i + + ) {
if ( blockmap [ 0 ] [ i ] & 8 ) { blockmap [ 0 ] [ i ] = 8 ; }
if ( blockmap [ 0 ] [ i ] & 4 ) { blockmap [ 0 ] [ i ] = 4 ; }
if ( blockmap [ 0 ] [ i ] & 2 ) { blockmap [ 0 ] [ i ] = 2 ; }
if ( blockmap [ 0 ] [ i ] & 1 ) { blockmap [ 0 ] [ i ] = 1 ; }
}
2012-12-30 17:55:05 +04:00
2008-10-08 19:15:49 +04:00
/* Combine blocks of the same type */
i = 0 ;
do {
if ( blockmap [ 0 ] [ i ] = = blockmap [ 0 ] [ i + 1 ] ) {
blockmap [ 1 ] [ i ] + = blockmap [ 1 ] [ i + 1 ] ;
for ( j = i + 1 ; j < blocks ; j + + ) {
blockmap [ 0 ] [ j ] = blockmap [ 0 ] [ j + 1 ] ;
blockmap [ 1 ] [ j ] = blockmap [ 1 ] [ j + 1 ] ;
}
blocks - - ;
} else {
i + + ;
}
} while ( i < blocks ) ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
/* Put the adjusted block data back into typemap */
j = 0 ;
2010-04-06 13:14:28 +04:00
for ( i = 0 ; i < blocks ; i + + ) {
2008-09-03 00:01:41 +04:00
if ( ( blockmap [ 1 ] [ i ] < 3 ) & & ( blockmap [ 0 ] [ i ] ! = 32 ) ) { /* Shift character(s) needed */
for ( k = 0 ; k < blockmap [ 1 ] [ i ] ; k + + ) {
typemap [ j + k ] = blockmap [ 0 ] [ i ] + 64 ;
}
} else { /* Latch character (or byte mode) needed */
for ( k = 0 ; k < blockmap [ 1 ] [ i ] ; k + + ) {
typemap [ j + k ] = blockmap [ 0 ] [ i ] ;
}
}
j + = blockmap [ 1 ] [ i ] ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
/* Don't shift an initial capital letter */
if ( typemap [ 0 ] = = 65 ) { typemap [ 0 ] = 1 ; } ;
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
/* Problem characters (those that appear in different tables with different values) can now be resolved into their tables */
for ( i = 0 ; i < maplength ; i + + ) {
2009-01-24 17:35:46 +03:00
if ( ( charmap [ i ] > = 300 ) & & ( charmap [ i ] < 400 ) ) {
2008-09-03 00:01:41 +04:00
curtable = typemap [ i ] ;
if ( curtable > 64 ) {
curtable - = 64 ;
}
switch ( charmap [ i ] ) {
case 300 : /* Carriage Return */
switch ( curtable ) {
case PUNC : charmap [ i ] = 1 ; break ;
case MIXED : charmap [ i ] = 14 ; break ;
}
break ;
case 301 : /* Comma */
switch ( curtable ) {
case PUNC : charmap [ i ] = 17 ; break ;
case DIGIT : charmap [ i ] = 12 ; break ;
}
break ;
case 302 : /* Full Stop */
switch ( curtable ) {
case PUNC : charmap [ i ] = 19 ; break ;
case DIGIT : charmap [ i ] = 13 ; break ;
}
break ;
}
}
}
2009-10-06 23:03:00 +04:00
* binary_string = ' \0 ' ;
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
curtable = UPPER ; /* start with UPPER table */
2008-10-06 23:46:48 +04:00
lasttable = UPPER ;
2008-09-03 00:01:41 +04:00
for ( i = 0 ; i < maplength ; i + + ) {
newtable = curtable ;
2009-01-24 17:35:46 +03:00
if ( ( typemap [ i ] ! = curtable ) & & ( charmap [ i ] < 400 ) ) {
2008-09-03 00:01:41 +04:00
/* Change table */
if ( curtable = = BINARY ) {
/* If ending binary mode the current table is the same as when entering binary mode */
curtable = lasttable ;
newtable = lasttable ;
}
if ( typemap [ i ] > 64 ) {
/* Shift character */
switch ( typemap [ i ] ) {
case ( 64 + UPPER ) : /* To UPPER */
switch ( curtable ) {
case LOWER : /* US */
concat ( binary_string , hexbit [ 28 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " US " ) ;
2008-09-03 00:01:41 +04:00
break ;
case MIXED : /* UL */
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
newtable = UPPER ;
break ;
case PUNC : /* UL */
concat ( binary_string , hexbit [ 31 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
newtable = UPPER ;
break ;
case DIGIT : /* US */
concat ( binary_string , pentbit [ 15 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " US " ) ;
2008-09-03 00:01:41 +04:00
break ;
}
break ;
case ( 64 + LOWER ) : /* To LOWER */
switch ( curtable ) {
case UPPER : /* LL */
concat ( binary_string , hexbit [ 28 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " LL " ) ;
2008-09-03 00:01:41 +04:00
newtable = LOWER ;
break ;
case MIXED : /* LL */
concat ( binary_string , hexbit [ 28 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " LL " ) ;
2008-09-03 00:01:41 +04:00
newtable = LOWER ;
break ;
case PUNC : /* UL LL */
concat ( binary_string , hexbit [ 31 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 28 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " LL " ) ;
2008-09-03 00:01:41 +04:00
newtable = LOWER ;
break ;
case DIGIT : /* UL LL */
concat ( binary_string , pentbit [ 14 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 28 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " LL " ) ;
2008-09-03 00:01:41 +04:00
newtable = LOWER ;
break ;
}
break ;
case ( 64 + MIXED ) : /* To MIXED */
switch ( curtable ) {
case UPPER : /* ML */
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " ML " ) ;
2008-09-03 00:01:41 +04:00
newtable = MIXED ;
break ;
case LOWER : /* ML */
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " ML " ) ;
2008-09-03 00:01:41 +04:00
newtable = MIXED ;
break ;
case PUNC : /* UL ML */
concat ( binary_string , hexbit [ 31 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " ML " ) ;
2008-09-03 00:01:41 +04:00
newtable = MIXED ;
break ;
case DIGIT : /* UL ML */
concat ( binary_string , pentbit [ 14 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " ML " ) ;
2008-09-03 00:01:41 +04:00
newtable = MIXED ;
break ;
}
break ;
case ( 64 + PUNC ) : /* To PUNC */
switch ( curtable ) {
case UPPER : /* PS */
concat ( binary_string , hexbit [ 0 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " PS " ) ;
2008-09-03 00:01:41 +04:00
break ;
case LOWER : /* PS */
concat ( binary_string , hexbit [ 0 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " PS " ) ;
2008-09-03 00:01:41 +04:00
break ;
case MIXED : /* PS */
concat ( binary_string , hexbit [ 0 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " PS " ) ;
2008-09-03 00:01:41 +04:00
break ;
case DIGIT : /* PS */
concat ( binary_string , pentbit [ 0 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " PS " ) ;
2008-09-03 00:01:41 +04:00
break ;
}
break ;
case ( 64 + DIGIT ) : /* To DIGIT */
switch ( curtable ) {
case UPPER : /* DL */
concat ( binary_string , hexbit [ 30 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " DL " ) ;
2008-09-03 00:01:41 +04:00
newtable = DIGIT ;
break ;
case LOWER : /* DL */
concat ( binary_string , hexbit [ 30 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " DL " ) ;
2008-09-03 00:01:41 +04:00
newtable = DIGIT ;
break ;
case MIXED : /* UL DL */
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 30 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " DL " ) ;
2008-09-03 00:01:41 +04:00
newtable = DIGIT ;
break ;
case PUNC : /* UL DL */
concat ( binary_string , hexbit [ 31 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 30 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " DL " ) ;
2008-09-03 00:01:41 +04:00
newtable = DIGIT ;
break ;
}
break ;
}
} else {
/* Latch character */
switch ( typemap [ i ] ) {
case UPPER : /* To UPPER */
switch ( curtable ) {
case LOWER : /* ML UL */
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " ML " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
newtable = UPPER ;
break ;
case MIXED : /* UL */
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
newtable = UPPER ;
break ;
case PUNC : /* UL */
concat ( binary_string , hexbit [ 31 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
newtable = UPPER ;
break ;
case DIGIT : /* UL */
concat ( binary_string , pentbit [ 14 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
newtable = UPPER ;
break ;
}
break ;
case LOWER : /* To LOWER */
switch ( curtable ) {
case UPPER : /* LL */
concat ( binary_string , hexbit [ 28 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " LL " ) ;
2008-09-03 00:01:41 +04:00
newtable = LOWER ;
break ;
case MIXED : /* LL */
concat ( binary_string , hexbit [ 28 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " LL " ) ;
2008-09-03 00:01:41 +04:00
newtable = LOWER ;
break ;
case PUNC : /* UL LL */
concat ( binary_string , hexbit [ 31 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 28 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " LL " ) ;
2008-09-03 00:01:41 +04:00
newtable = LOWER ;
break ;
case DIGIT : /* UL LL */
concat ( binary_string , pentbit [ 14 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 28 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " LL " ) ;
2008-09-03 00:01:41 +04:00
newtable = LOWER ;
break ;
}
break ;
case MIXED : /* To MIXED */
switch ( curtable ) {
case UPPER : /* ML */
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " ML " ) ;
2008-09-03 00:01:41 +04:00
newtable = MIXED ;
break ;
case LOWER : /* ML */
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " ML " ) ;
2008-09-03 00:01:41 +04:00
newtable = MIXED ;
break ;
case PUNC : /* UL ML */
concat ( binary_string , hexbit [ 31 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " ML " ) ;
2008-09-03 00:01:41 +04:00
newtable = MIXED ;
break ;
case DIGIT : /* UL ML */
concat ( binary_string , pentbit [ 14 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " ML " ) ;
2008-09-03 00:01:41 +04:00
newtable = MIXED ;
break ;
}
break ;
case PUNC : /* To PUNC */
switch ( curtable ) {
case UPPER : /* ML PL */
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " ML " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 30 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " PL " ) ;
2008-09-03 00:01:41 +04:00
newtable = PUNC ;
break ;
case LOWER : /* ML PL */
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " ML " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 30 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " PL " ) ;
2008-09-03 00:01:41 +04:00
newtable = PUNC ;
break ;
case MIXED : /* PL */
concat ( binary_string , hexbit [ 30 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " PL " ) ;
2008-09-03 00:01:41 +04:00
newtable = PUNC ;
break ;
case DIGIT : /* UL ML PL */
concat ( binary_string , pentbit [ 14 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " ML " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 30 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " PL " ) ;
2008-09-03 00:01:41 +04:00
newtable = PUNC ;
break ;
}
break ;
case DIGIT : /* To DIGIT */
switch ( curtable ) {
case UPPER : /* DL */
concat ( binary_string , hexbit [ 30 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " DL " ) ;
2008-09-03 00:01:41 +04:00
newtable = DIGIT ;
break ;
case LOWER : /* DL */
concat ( binary_string , hexbit [ 30 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " DL " ) ;
2008-09-03 00:01:41 +04:00
newtable = DIGIT ;
break ;
case MIXED : /* UL DL */
concat ( binary_string , hexbit [ 29 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 30 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " DL " ) ;
2008-09-03 00:01:41 +04:00
newtable = DIGIT ;
break ;
case PUNC : /* UL DL */
concat ( binary_string , hexbit [ 31 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 30 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " DL " ) ;
2008-09-03 00:01:41 +04:00
newtable = DIGIT ;
break ;
}
break ;
case BINARY : /* To BINARY */
lasttable = curtable ;
switch ( curtable ) {
case UPPER : /* BS */
concat ( binary_string , hexbit [ 31 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " BS " ) ;
2008-09-03 00:01:41 +04:00
newtable = BINARY ;
break ;
case LOWER : /* BS */
concat ( binary_string , hexbit [ 31 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " BS " ) ;
2008-09-03 00:01:41 +04:00
newtable = BINARY ;
break ;
case MIXED : /* BS */
concat ( binary_string , hexbit [ 31 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " BS " ) ;
2008-09-03 00:01:41 +04:00
newtable = BINARY ;
break ;
case PUNC : /* UL BS */
concat ( binary_string , hexbit [ 31 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 31 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " BS " ) ;
2008-09-03 00:01:41 +04:00
newtable = BINARY ;
break ;
case DIGIT : /* UL BS */
concat ( binary_string , pentbit [ 14 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " UL " ) ;
2008-09-03 00:01:41 +04:00
concat ( binary_string , hexbit [ 31 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " BS " ) ;
2008-09-03 00:01:41 +04:00
newtable = BINARY ;
break ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
bytes = 0 ;
do {
bytes + + ;
} while ( typemap [ i + ( bytes - 1 ) ] = = BINARY ) ;
2009-08-04 20:50:24 +04:00
bytes - - ;
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
if ( bytes > 2079 ) {
return ERROR_TOO_LONG ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
if ( bytes > 31 ) { /* Put 00000 followed by 11-bit number of bytes less 31 */
int adjusted ;
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
adjusted = bytes - 31 ;
concat ( binary_string , " 00000 " ) ;
if ( adjusted & 0x400 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( adjusted & 0x200 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( adjusted & 0x100 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( adjusted & 0x80 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( adjusted & 0x40 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( adjusted & 0x20 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( adjusted & 0x10 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( adjusted & 0x08 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( adjusted & 0x04 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( adjusted & 0x02 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( adjusted & 0x01 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
} else { /* Put 5-bit number of bytes */
if ( bytes & 0x10 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( bytes & 0x08 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( bytes & 0x04 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( bytes & 0x02 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( bytes & 0x01 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
}
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " (%d bytes) " , bytes ) ;
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
break ;
}
}
}
/* Add data to the binary string */
curtable = newtable ;
chartype = typemap [ i ] ;
if ( chartype > 64 ) { chartype - = 64 ; }
switch ( chartype ) {
case UPPER :
case LOWER :
case MIXED :
case PUNC :
2009-01-16 08:50:22 +03:00
if ( charmap [ i ] > = 400 ) {
concat ( binary_string , tribit [ charmap [ i ] - 400 ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " FLG(%d) " , charmap [ i ] - 400 ) ;
2009-01-16 08:50:22 +03:00
} else {
concat ( binary_string , hexbit [ charmap [ i ] ] ) ;
2009-01-24 17:35:46 +03:00
if ( ! ( ( chartype = = PUNC ) & & ( charmap [ i ] = = 0 ) ) )
if ( debug ) printf ( " %d " , charmap [ i ] ) ;
2009-01-16 08:50:22 +03:00
}
2008-09-03 00:01:41 +04:00
break ;
case DIGIT :
concat ( binary_string , pentbit [ charmap [ i ] ] ) ;
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " %d " , charmap [ i ] ) ;
2008-09-03 00:01:41 +04:00
break ;
case BINARY :
if ( charmap [ i ] & 0x80 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( charmap [ i ] & 0x40 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( charmap [ i ] & 0x20 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( charmap [ i ] & 0x10 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( charmap [ i ] & 0x08 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( charmap [ i ] & 0x04 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( charmap [ i ] & 0x02 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( charmap [ i ] & 0x01 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " %d " , charmap [ i ] ) ;
2008-09-03 00:01:41 +04:00
break ;
}
}
2012-12-30 17:55:05 +04:00
2009-01-24 17:35:46 +03:00
if ( debug ) printf ( " \n " ) ;
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
if ( strlen ( binary_string ) > 14970 ) {
return ERROR_TOO_LONG ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
return 0 ;
}
2009-09-29 13:45:46 +04:00
int aztec ( struct zint_symbol * symbol , unsigned char source [ ] , int length )
2008-09-03 00:01:41 +04:00
{
2008-11-08 02:42:53 +03:00
int x , y , i , j , data_blocks , ecc_blocks , layers , total_bits ;
2008-09-03 00:01:41 +04:00
char binary_string [ 20000 ] , bit_pattern [ 20045 ] , descriptor [ 42 ] ;
char adjusted_string [ 20000 ] ;
unsigned char desc_data [ 4 ] , desc_ecc [ 6 ] ;
int err_code , ecc_level , compact , data_length , data_maxsize , codeword_size , adjusted_length ;
2009-05-15 02:23:01 +04:00
int remainder , padbits , count , gs1 , adjustment_size ;
2009-12-08 00:33:06 +03:00
int debug = 0 , reader = 0 ;
int comp_loop = 4 ;
2009-08-06 23:44:30 +04:00
2009-09-29 13:45:46 +04:00
# ifndef _MSC_VER
2009-10-06 23:03:00 +04:00
unsigned char local_source [ length + 1 ] ;
2009-09-29 13:45:46 +04:00
# else
2009-10-06 23:03:00 +04:00
unsigned char * local_source = ( unsigned char * ) _alloca ( length + 1 ) ;
2009-09-29 13:45:46 +04:00
# endif
2008-10-08 18:18:32 +04:00
memset ( binary_string , 0 , 20000 ) ;
memset ( adjusted_string , 0 , 20000 ) ;
2009-01-16 08:50:22 +03:00
if ( symbol - > input_mode = = GS1_MODE ) { gs1 = 1 ; } else { gs1 = 0 ; }
2009-12-08 00:33:06 +03:00
if ( symbol - > output_options & READER_INIT ) { reader = 1 ; comp_loop = 1 ; }
if ( ( gs1 = = 1 ) & & ( reader = = 1 ) ) {
strcpy ( symbol - > errtxt , " Cannot encode in GS1 and Reader Initialisation mode at the same time " ) ;
return ERROR_INVALID_OPTION ;
}
2012-12-30 17:55:05 +04:00
2009-09-29 13:45:46 +04:00
switch ( symbol - > input_mode ) {
case DATA_MODE :
2009-10-06 23:03:00 +04:00
case GS1_MODE :
memcpy ( local_source , source , length ) ;
2009-09-29 13:45:46 +04:00
local_source [ length ] = ' \0 ' ;
break ;
case UNICODE_MODE :
err_code = latin1_process ( symbol , source , local_source , & length ) ;
if ( err_code ! = 0 ) { return err_code ; }
break ;
}
/* Aztec code can't handle NULL characters */
for ( i = 0 ; i < length ; i + + ) {
if ( local_source [ i ] = = ' \0 ' ) {
strcpy ( symbol - > errtxt , " Invalid character (NULL) in input data " ) ;
return ERROR_INVALID_DATA ;
}
}
2009-10-06 23:03:00 +04:00
err_code = aztec_text_process ( local_source , length , binary_string , gs1 ) ;
2012-12-30 17:55:05 +04:00
2008-10-08 18:18:32 +04:00
2008-09-03 00:01:41 +04:00
if ( err_code ! = 0 ) {
2009-05-15 02:23:01 +04:00
strcpy ( symbol - > errtxt , " Input too long or too many extended ASCII characters " ) ;
2008-09-03 00:01:41 +04:00
return err_code ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
if ( ! ( ( symbol - > option_1 > = - 1 ) & & ( symbol - > option_1 < = 4 ) ) ) {
2009-05-15 02:23:01 +04:00
strcpy ( symbol - > errtxt , " Invalid error correction level - using default instead " ) ;
2008-09-03 00:01:41 +04:00
err_code = WARN_INVALID_OPTION ;
symbol - > option_1 = - 1 ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
ecc_level = symbol - > option_1 ;
2012-12-30 17:55:05 +04:00
2009-04-27 02:04:01 +04:00
if ( ( ecc_level = = - 1 ) | | ( ecc_level = = 0 ) ) {
2008-09-03 00:01:41 +04:00
ecc_level = 2 ;
}
2012-12-30 17:55:05 +04:00
2008-10-06 23:46:48 +04:00
data_length = strlen ( binary_string ) ;
2008-10-08 18:18:32 +04:00
2008-10-06 23:46:48 +04:00
layers = 0 ; /* Keep compiler happy! */
data_maxsize = 0 ; /* Keep compiler happy! */
2009-05-15 02:23:01 +04:00
adjustment_size = 0 ;
2008-09-03 00:01:41 +04:00
if ( symbol - > option_2 = = 0 ) { /* The size of the symbol can be determined by Zint */
do {
/* Decide what size symbol to use - the smallest that fits the data */
compact = 0 ; /* 1 = Aztec Compact, 0 = Normal Aztec */
layers = 0 ;
2009-04-27 02:04:01 +04:00
2008-09-03 00:01:41 +04:00
switch ( ecc_level ) {
/* For each level of error correction work out the smallest symbol which
the data will fit in */
case 1 : for ( i = 32 ; i > 0 ; i - - ) {
2009-05-15 02:23:01 +04:00
if ( ( data_length + adjustment_size ) < Aztec10DataSizes [ i - 1 ] ) {
2008-09-03 00:01:41 +04:00
layers = i ;
compact = 0 ;
data_maxsize = Aztec10DataSizes [ i - 1 ] ;
}
}
2009-12-08 00:33:06 +03:00
for ( i = comp_loop ; i > 0 ; i - - ) {
2009-05-15 02:23:01 +04:00
if ( ( data_length + adjustment_size ) < AztecCompact10DataSizes [ i - 1 ] ) {
2008-09-03 00:01:41 +04:00
layers = i ;
compact = 1 ;
data_maxsize = AztecCompact10DataSizes [ i - 1 ] ;
}
}
break ;
case 2 : for ( i = 32 ; i > 0 ; i - - ) {
2009-05-15 02:23:01 +04:00
if ( ( data_length + adjustment_size ) < Aztec23DataSizes [ i - 1 ] ) {
2008-09-03 00:01:41 +04:00
layers = i ;
compact = 0 ;
data_maxsize = Aztec23DataSizes [ i - 1 ] ;
}
}
2009-12-08 00:33:06 +03:00
for ( i = comp_loop ; i > 0 ; i - - ) {
2009-05-15 02:23:01 +04:00
if ( ( data_length + adjustment_size ) < AztecCompact23DataSizes [ i - 1 ] ) {
2008-09-03 00:01:41 +04:00
layers = i ;
compact = 1 ;
data_maxsize = AztecCompact23DataSizes [ i - 1 ] ;
}
}
break ;
case 3 : for ( i = 32 ; i > 0 ; i - - ) {
2009-05-15 02:23:01 +04:00
if ( ( data_length + adjustment_size ) < Aztec36DataSizes [ i - 1 ] ) {
2008-09-03 00:01:41 +04:00
layers = i ;
compact = 0 ;
data_maxsize = Aztec36DataSizes [ i - 1 ] ;
}
}
2009-12-08 00:33:06 +03:00
for ( i = comp_loop ; i > 0 ; i - - ) {
2009-05-15 02:23:01 +04:00
if ( ( data_length + adjustment_size ) < AztecCompact36DataSizes [ i - 1 ] ) {
2008-09-03 00:01:41 +04:00
layers = i ;
compact = 1 ;
data_maxsize = AztecCompact36DataSizes [ i - 1 ] ;
}
}
break ;
case 4 : for ( i = 32 ; i > 0 ; i - - ) {
2009-05-15 02:23:01 +04:00
if ( ( data_length + adjustment_size ) < Aztec50DataSizes [ i - 1 ] ) {
2008-09-03 00:01:41 +04:00
layers = i ;
compact = 0 ;
data_maxsize = Aztec50DataSizes [ i - 1 ] ;
}
}
2009-12-08 00:33:06 +03:00
for ( i = comp_loop ; i > 0 ; i - - ) {
2009-05-15 02:23:01 +04:00
if ( ( data_length + adjustment_size ) < AztecCompact50DataSizes [ i - 1 ] ) {
2008-09-03 00:01:41 +04:00
layers = i ;
compact = 1 ;
data_maxsize = AztecCompact50DataSizes [ i - 1 ] ;
}
}
break ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
if ( layers = = 0 ) { /* Couldn't find a symbol which fits the data */
2009-05-15 02:23:01 +04:00
strcpy ( symbol - > errtxt , " Input too long (too many bits for selected ECC) " ) ;
2008-09-03 00:01:41 +04:00
return ERROR_TOO_LONG ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
/* Determine codeword bitlength - Table 3 */
2008-10-06 23:46:48 +04:00
codeword_size = 6 ; /* if (layers <= 2) */
2008-09-03 00:01:41 +04:00
if ( ( layers > = 3 ) & & ( layers < = 8 ) ) { codeword_size = 8 ; }
if ( ( layers > = 9 ) & & ( layers < = 22 ) ) { codeword_size = 10 ; }
if ( layers > = 23 ) { codeword_size = 12 ; }
2012-12-30 17:55:05 +04:00
2009-08-04 22:59:29 +04:00
j = 0 ; i = 0 ;
do {
if ( ( j + 1 ) % codeword_size = = 0 ) {
2008-11-08 02:42:53 +03:00
/* Last bit of codeword */
2009-08-04 22:59:29 +04:00
int t , done = 0 ;
count = 0 ;
2012-12-30 17:55:05 +04:00
2009-08-04 22:59:29 +04:00
/* Discover how many '1's in current codeword */
for ( t = 0 ; t < ( codeword_size - 1 ) ; t + + ) {
if ( binary_string [ ( i - ( codeword_size - 1 ) ) + t ] = = ' 1 ' ) count + + ;
}
2012-12-30 17:55:05 +04:00
2009-08-04 22:59:29 +04:00
if ( count = = ( codeword_size - 1 ) ) {
2008-11-08 02:42:53 +03:00
adjusted_string [ j ] = ' 0 ' ;
j + + ;
2009-08-04 22:59:29 +04:00
done = 1 ;
2008-11-08 02:42:53 +03:00
}
2012-12-30 17:55:05 +04:00
2008-11-08 02:42:53 +03:00
if ( count = = 0 ) {
adjusted_string [ j ] = ' 1 ' ;
j + + ;
2009-08-04 22:59:29 +04:00
done = 1 ;
}
2012-12-30 17:55:05 +04:00
2009-08-04 22:59:29 +04:00
if ( done = = 0 ) {
adjusted_string [ j ] = binary_string [ i ] ;
j + + ;
i + + ;
2008-11-08 02:42:53 +03:00
}
}
adjusted_string [ j ] = binary_string [ i ] ;
j + + ;
2009-08-04 22:59:29 +04:00
i + + ;
} while ( i < = ( data_length + 1 ) ) ;
2008-11-08 02:42:53 +03:00
adjusted_string [ j ] = ' \0 ' ;
adjusted_length = strlen ( adjusted_string ) ;
2009-05-15 02:23:01 +04:00
adjustment_size = adjusted_length - data_length ;
2012-12-30 17:55:05 +04:00
2010-04-06 13:14:28 +04:00
/* Add padding */
2008-11-08 02:42:53 +03:00
remainder = adjusted_length % codeword_size ;
2012-12-30 17:55:05 +04:00
2008-11-08 02:42:53 +03:00
padbits = codeword_size - remainder ;
if ( padbits = = codeword_size ) { padbits = 0 ; }
for ( i = 0 ; i < padbits ; i + + ) {
concat ( adjusted_string , " 1 " ) ;
}
2008-09-03 00:01:41 +04:00
adjusted_length = strlen ( adjusted_string ) ;
2012-12-30 17:55:05 +04:00
2008-11-08 02:42:53 +03:00
count = 0 ;
for ( i = ( adjusted_length - codeword_size ) ; i < adjusted_length ; i + + ) {
if ( adjusted_string [ i ] = = ' 1 ' ) { count + + ; }
}
if ( count = = codeword_size ) { adjusted_string [ adjusted_length - 1 ] = ' 0 ' ; }
2010-04-06 13:14:28 +04:00
if ( debug ) {
printf ( " Codewords: \n " ) ;
for ( i = 0 ; i < ( adjusted_length / codeword_size ) ; i + + ) {
for ( j = 0 ; j < codeword_size ; j + + ) {
printf ( " %c " , adjusted_string [ ( i * codeword_size ) + j ] ) ;
}
printf ( " \n " ) ;
}
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
} while ( adjusted_length > data_maxsize ) ;
/* This loop will only repeat on the rare occasions when the rule about not having all 1s or all 0s
means that the binary string has had to be lengthened beyond the maximum number of bits that can
be encoded in a symbol of the selected size */
} else { /* The size of the symbol has been specified by the user */
2009-12-08 00:33:06 +03:00
if ( ( reader = = 1 ) & & ( ( symbol - > option_2 > = 2 ) & & ( symbol - > option_2 < = 4 ) ) ) {
symbol - > option_2 = 5 ;
}
2008-09-03 00:01:41 +04:00
if ( ( symbol - > option_2 > = 1 ) & & ( symbol - > option_2 < = 4 ) ) {
compact = 1 ;
layers = symbol - > option_2 ;
}
if ( ( symbol - > option_2 > = 5 ) & & ( symbol - > option_2 < = 36 ) ) {
compact = 0 ;
layers = symbol - > option_2 - 4 ;
}
if ( ( symbol - > option_2 < 0 ) | | ( symbol - > option_2 > 36 ) ) {
2009-05-15 02:23:01 +04:00
strcpy ( symbol - > errtxt , " Invalid Aztec Code size " ) ;
2008-09-03 00:01:41 +04:00
return ERROR_INVALID_OPTION ;
}
/* Determine codeword bitlength - Table 3 */
if ( ( layers > = 0 ) & & ( layers < = 2 ) ) { codeword_size = 6 ; }
if ( ( layers > = 3 ) & & ( layers < = 8 ) ) { codeword_size = 8 ; }
if ( ( layers > = 9 ) & & ( layers < = 22 ) ) { codeword_size = 10 ; }
if ( layers > = 23 ) { codeword_size = 12 ; }
2012-12-30 17:55:05 +04:00
2009-08-04 22:59:29 +04:00
j = 0 ; i = 0 ;
do {
if ( ( j + 1 ) % codeword_size = = 0 ) {
2008-11-08 02:42:53 +03:00
/* Last bit of codeword */
2009-08-04 22:59:29 +04:00
int t , done = 0 ;
count = 0 ;
2012-12-30 17:55:05 +04:00
2009-08-04 22:59:29 +04:00
/* Discover how many '1's in current codeword */
for ( t = 0 ; t < ( codeword_size - 1 ) ; t + + ) {
if ( binary_string [ ( i - ( codeword_size - 1 ) ) + t ] = = ' 1 ' ) count + + ;
}
2012-12-30 17:55:05 +04:00
2009-08-04 22:59:29 +04:00
if ( count = = ( codeword_size - 1 ) ) {
2008-11-08 02:42:53 +03:00
adjusted_string [ j ] = ' 0 ' ;
j + + ;
2009-08-04 22:59:29 +04:00
done = 1 ;
2008-11-08 02:42:53 +03:00
}
2012-12-30 17:55:05 +04:00
2008-11-08 02:42:53 +03:00
if ( count = = 0 ) {
adjusted_string [ j ] = ' 1 ' ;
j + + ;
2009-08-04 22:59:29 +04:00
done = 1 ;
}
2012-12-30 17:55:05 +04:00
2009-08-04 22:59:29 +04:00
if ( done = = 0 ) {
adjusted_string [ j ] = binary_string [ i ] ;
j + + ;
i + + ;
2008-11-08 02:42:53 +03:00
}
}
adjusted_string [ j ] = binary_string [ i ] ;
j + + ;
2009-08-04 22:59:29 +04:00
i + + ;
} while ( i < = ( data_length + 1 ) ) ;
2008-11-08 02:42:53 +03:00
adjusted_string [ j ] = ' \0 ' ;
adjusted_length = strlen ( adjusted_string ) ;
2012-12-30 17:55:05 +04:00
2008-11-08 02:42:53 +03:00
remainder = adjusted_length % codeword_size ;
2012-12-30 17:55:05 +04:00
2008-11-08 02:42:53 +03:00
padbits = codeword_size - remainder ;
if ( padbits = = codeword_size ) { padbits = 0 ; }
for ( i = 0 ; i < padbits ; i + + ) {
concat ( adjusted_string , " 1 " ) ;
}
2008-09-03 00:01:41 +04:00
adjusted_length = strlen ( adjusted_string ) ;
2012-12-30 17:55:05 +04:00
2008-11-08 02:42:53 +03:00
count = 0 ;
for ( i = ( adjusted_length - codeword_size ) ; i < adjusted_length ; i + + ) {
if ( adjusted_string [ i ] = = ' 1 ' ) { count + + ; }
}
if ( count = = codeword_size ) { adjusted_string [ adjusted_length - 1 ] = ' 0 ' ; }
2008-09-03 00:01:41 +04:00
/* Check if the data actually fits into the selected symbol size */
if ( compact ) {
data_maxsize = codeword_size * ( AztecCompactSizes [ layers - 1 ] - 3 ) ;
} else {
data_maxsize = codeword_size * ( AztecSizes [ layers - 1 ] - 3 ) ;
}
if ( adjusted_length > data_maxsize ) {
2009-05-15 02:23:01 +04:00
strcpy ( symbol - > errtxt , " Data too long for specified Aztec Code symbol size " ) ;
2008-09-03 00:01:41 +04:00
return ERROR_TOO_LONG ;
}
2012-12-30 17:55:05 +04:00
2010-04-06 13:14:28 +04:00
if ( debug ) {
printf ( " Codewords: \n " ) ;
for ( i = 0 ; i < ( adjusted_length / codeword_size ) ; i + + ) {
for ( j = 0 ; j < codeword_size ; j + + ) {
printf ( " %c " , adjusted_string [ ( i * codeword_size ) + j ] ) ;
}
printf ( " \n " ) ;
}
}
2008-09-03 00:01:41 +04:00
}
2012-12-30 17:55:05 +04:00
2009-12-08 00:33:06 +03:00
if ( reader & & ( layers > 22 ) ) {
strcpy ( symbol - > errtxt , " Data too long for reader initialisation symbol " ) ;
return ERROR_TOO_LONG ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
data_blocks = adjusted_length / codeword_size ;
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
if ( compact ) {
ecc_blocks = AztecCompactSizes [ layers - 1 ] - data_blocks ;
} else {
ecc_blocks = AztecSizes [ layers - 1 ] - data_blocks ;
}
2012-12-30 17:55:05 +04:00
2009-06-19 22:29:49 +04:00
if ( debug ) {
printf ( " Generating a " ) ;
if ( compact ) { printf ( " compact " ) ; } else { printf ( " full-size " ) ; }
printf ( " symbol with %d layers \n " , layers ) ;
printf ( " Requires " ) ;
if ( compact ) { printf ( " %d " , AztecCompactSizes [ layers - 1 ] ) ; } else { printf ( " %d " , AztecSizes [ layers - 1 ] ) ; }
printf ( " codewords of %d-bits \n " , codeword_size ) ;
printf ( " (%d data words, %d ecc words) \n " , data_blocks , ecc_blocks ) ;
}
# ifndef _MSC_VER
2009-07-16 19:24:46 +04:00
unsigned int data_part [ data_blocks + 3 ] , ecc_part [ ecc_blocks + 3 ] ;
2009-06-19 22:29:49 +04:00
# else
2009-10-06 23:03:00 +04:00
unsigned int * data_part = ( unsigned int * ) _alloca ( ( data_blocks + 3 ) * sizeof ( unsigned int ) ) ;
unsigned int * ecc_part = ( unsigned int * ) _alloca ( ( ecc_blocks + 3 ) * sizeof ( unsigned int ) ) ;
2009-06-19 22:29:49 +04:00
# endif
2008-09-03 00:01:41 +04:00
/* Copy across data into separate integers */
2009-06-19 22:29:49 +04:00
memset ( data_part , 0 , ( data_blocks + 2 ) * sizeof ( int ) ) ;
memset ( ecc_part , 0 , ( ecc_blocks + 2 ) * sizeof ( int ) ) ;
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
/* Split into codewords and calculate reed-colomon error correction codes */
switch ( codeword_size ) {
case 6 :
for ( i = 0 ; i < data_blocks ; i + + ) {
if ( adjusted_string [ i * codeword_size ] = = ' 1 ' ) { data_part [ i ] + = 32 ; }
if ( adjusted_string [ ( i * codeword_size ) + 1 ] = = ' 1 ' ) { data_part [ i ] + = 16 ; }
if ( adjusted_string [ ( i * codeword_size ) + 2 ] = = ' 1 ' ) { data_part [ i ] + = 8 ; }
if ( adjusted_string [ ( i * codeword_size ) + 3 ] = = ' 1 ' ) { data_part [ i ] + = 4 ; }
if ( adjusted_string [ ( i * codeword_size ) + 4 ] = = ' 1 ' ) { data_part [ i ] + = 2 ; }
if ( adjusted_string [ ( i * codeword_size ) + 5 ] = = ' 1 ' ) { data_part [ i ] + = 1 ; }
}
rs_init_gf ( 0x43 ) ;
rs_init_code ( ecc_blocks , 1 ) ;
rs_encode_long ( data_blocks , data_part , ecc_part ) ;
for ( i = ( ecc_blocks - 1 ) ; i > = 0 ; i - - ) {
if ( ecc_part [ i ] & 0x20 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x10 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x08 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x04 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x02 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x01 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
}
2008-10-12 22:52:54 +04:00
rs_free ( ) ;
2008-09-03 00:01:41 +04:00
break ;
case 8 :
for ( i = 0 ; i < data_blocks ; i + + ) {
if ( adjusted_string [ i * codeword_size ] = = ' 1 ' ) { data_part [ i ] + = 128 ; }
if ( adjusted_string [ ( i * codeword_size ) + 1 ] = = ' 1 ' ) { data_part [ i ] + = 64 ; }
if ( adjusted_string [ ( i * codeword_size ) + 2 ] = = ' 1 ' ) { data_part [ i ] + = 32 ; }
if ( adjusted_string [ ( i * codeword_size ) + 3 ] = = ' 1 ' ) { data_part [ i ] + = 16 ; }
if ( adjusted_string [ ( i * codeword_size ) + 4 ] = = ' 1 ' ) { data_part [ i ] + = 8 ; }
if ( adjusted_string [ ( i * codeword_size ) + 5 ] = = ' 1 ' ) { data_part [ i ] + = 4 ; }
if ( adjusted_string [ ( i * codeword_size ) + 6 ] = = ' 1 ' ) { data_part [ i ] + = 2 ; }
if ( adjusted_string [ ( i * codeword_size ) + 7 ] = = ' 1 ' ) { data_part [ i ] + = 1 ; }
}
rs_init_gf ( 0x12d ) ;
rs_init_code ( ecc_blocks , 1 ) ;
rs_encode_long ( data_blocks , data_part , ecc_part ) ;
for ( i = ( ecc_blocks - 1 ) ; i > = 0 ; i - - ) {
if ( ecc_part [ i ] & 0x80 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x40 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x20 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x10 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x08 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x04 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x02 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x01 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
}
2008-10-12 22:52:54 +04:00
rs_free ( ) ;
2008-09-03 00:01:41 +04:00
break ;
case 10 :
for ( i = 0 ; i < data_blocks ; i + + ) {
if ( adjusted_string [ i * codeword_size ] = = ' 1 ' ) { data_part [ i ] + = 512 ; }
if ( adjusted_string [ ( i * codeword_size ) + 1 ] = = ' 1 ' ) { data_part [ i ] + = 256 ; }
if ( adjusted_string [ ( i * codeword_size ) + 2 ] = = ' 1 ' ) { data_part [ i ] + = 128 ; }
if ( adjusted_string [ ( i * codeword_size ) + 3 ] = = ' 1 ' ) { data_part [ i ] + = 64 ; }
if ( adjusted_string [ ( i * codeword_size ) + 4 ] = = ' 1 ' ) { data_part [ i ] + = 32 ; }
if ( adjusted_string [ ( i * codeword_size ) + 5 ] = = ' 1 ' ) { data_part [ i ] + = 16 ; }
if ( adjusted_string [ ( i * codeword_size ) + 6 ] = = ' 1 ' ) { data_part [ i ] + = 8 ; }
if ( adjusted_string [ ( i * codeword_size ) + 7 ] = = ' 1 ' ) { data_part [ i ] + = 4 ; }
if ( adjusted_string [ ( i * codeword_size ) + 8 ] = = ' 1 ' ) { data_part [ i ] + = 2 ; }
if ( adjusted_string [ ( i * codeword_size ) + 9 ] = = ' 1 ' ) { data_part [ i ] + = 1 ; }
}
rs_init_gf ( 0x409 ) ;
rs_init_code ( ecc_blocks , 1 ) ;
rs_encode_long ( data_blocks , data_part , ecc_part ) ;
for ( i = ( ecc_blocks - 1 ) ; i > = 0 ; i - - ) {
if ( ecc_part [ i ] & 0x200 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x100 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x80 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x40 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x20 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x10 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x08 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x04 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x02 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x01 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
}
2008-10-12 22:52:54 +04:00
rs_free ( ) ;
2008-09-03 00:01:41 +04:00
break ;
case 12 :
for ( i = 0 ; i < data_blocks ; i + + ) {
if ( adjusted_string [ i * codeword_size ] = = ' 1 ' ) { data_part [ i ] + = 2048 ; }
if ( adjusted_string [ ( i * codeword_size ) + 1 ] = = ' 1 ' ) { data_part [ i ] + = 1024 ; }
if ( adjusted_string [ ( i * codeword_size ) + 2 ] = = ' 1 ' ) { data_part [ i ] + = 512 ; }
if ( adjusted_string [ ( i * codeword_size ) + 3 ] = = ' 1 ' ) { data_part [ i ] + = 256 ; }
if ( adjusted_string [ ( i * codeword_size ) + 4 ] = = ' 1 ' ) { data_part [ i ] + = 128 ; }
if ( adjusted_string [ ( i * codeword_size ) + 5 ] = = ' 1 ' ) { data_part [ i ] + = 64 ; }
if ( adjusted_string [ ( i * codeword_size ) + 6 ] = = ' 1 ' ) { data_part [ i ] + = 32 ; }
if ( adjusted_string [ ( i * codeword_size ) + 7 ] = = ' 1 ' ) { data_part [ i ] + = 16 ; }
if ( adjusted_string [ ( i * codeword_size ) + 8 ] = = ' 1 ' ) { data_part [ i ] + = 8 ; }
if ( adjusted_string [ ( i * codeword_size ) + 9 ] = = ' 1 ' ) { data_part [ i ] + = 4 ; }
if ( adjusted_string [ ( i * codeword_size ) + 10 ] = = ' 1 ' ) { data_part [ i ] + = 2 ; }
if ( adjusted_string [ ( i * codeword_size ) + 11 ] = = ' 1 ' ) { data_part [ i ] + = 1 ; }
}
rs_init_gf ( 0x1069 ) ;
rs_init_code ( ecc_blocks , 1 ) ;
rs_encode_long ( data_blocks , data_part , ecc_part ) ;
for ( i = ( ecc_blocks - 1 ) ; i > = 0 ; i - - ) {
if ( ecc_part [ i ] & 0x800 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x400 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x200 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x100 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x80 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x40 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x20 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x10 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x08 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x04 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x02 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
if ( ecc_part [ i ] & 0x01 ) { concat ( adjusted_string , " 1 " ) ; } else { concat ( adjusted_string , " 0 " ) ; }
}
2008-10-12 22:52:54 +04:00
rs_free ( ) ;
2008-09-03 00:01:41 +04:00
break ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
/* Invert the data so that actual data is on the outside and reed-solomon on the inside */
2008-10-08 18:18:32 +04:00
memset ( bit_pattern , ' 0 ' , 20045 ) ;
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
total_bits = ( data_blocks + ecc_blocks ) * codeword_size ;
for ( i = 0 ; i < total_bits ; i + + ) {
bit_pattern [ i ] = adjusted_string [ total_bits - i - 1 ] ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
/* Now add the symbol descriptor */
2008-10-08 18:18:32 +04:00
memset ( desc_data , 0 , 4 ) ;
memset ( desc_ecc , 0 , 6 ) ;
2009-01-25 22:48:06 +03:00
memset ( descriptor , 0 , 42 ) ;
2008-09-03 00:01:41 +04:00
if ( compact ) {
/* The first 2 bits represent the number of layers minus 1 */
2008-11-08 02:42:53 +03:00
if ( ( layers - 1 ) & 0x02 ) { descriptor [ 0 ] = ' 1 ' ; } else { descriptor [ 0 ] = ' 0 ' ; }
if ( ( layers - 1 ) & 0x01 ) { descriptor [ 1 ] = ' 1 ' ; } else { descriptor [ 1 ] = ' 0 ' ; }
2008-09-03 00:01:41 +04:00
/* The next 6 bits represent the number of data blocks minus 1 */
2009-12-08 00:33:06 +03:00
if ( reader ) {
descriptor [ 2 ] = ' 1 ' ;
} else {
if ( ( data_blocks - 1 ) & 0x20 ) { descriptor [ 2 ] = ' 1 ' ; } else { descriptor [ 2 ] = ' 0 ' ; }
}
2008-11-08 02:42:53 +03:00
if ( ( data_blocks - 1 ) & 0x10 ) { descriptor [ 3 ] = ' 1 ' ; } else { descriptor [ 3 ] = ' 0 ' ; }
if ( ( data_blocks - 1 ) & 0x08 ) { descriptor [ 4 ] = ' 1 ' ; } else { descriptor [ 4 ] = ' 0 ' ; }
if ( ( data_blocks - 1 ) & 0x04 ) { descriptor [ 5 ] = ' 1 ' ; } else { descriptor [ 5 ] = ' 0 ' ; }
if ( ( data_blocks - 1 ) & 0x02 ) { descriptor [ 6 ] = ' 1 ' ; } else { descriptor [ 6 ] = ' 0 ' ; }
if ( ( data_blocks - 1 ) & 0x01 ) { descriptor [ 7 ] = ' 1 ' ; } else { descriptor [ 7 ] = ' 0 ' ; }
descriptor [ 8 ] = ' \0 ' ;
2010-04-06 13:14:28 +04:00
if ( debug ) printf ( " Mode Message = %s \n " , descriptor ) ;
2008-09-03 00:01:41 +04:00
} else {
/* The first 5 bits represent the number of layers minus 1 */
2008-11-08 02:42:53 +03:00
if ( ( layers - 1 ) & 0x10 ) { descriptor [ 0 ] = ' 1 ' ; } else { descriptor [ 0 ] = ' 0 ' ; }
if ( ( layers - 1 ) & 0x08 ) { descriptor [ 1 ] = ' 1 ' ; } else { descriptor [ 1 ] = ' 0 ' ; }
if ( ( layers - 1 ) & 0x04 ) { descriptor [ 2 ] = ' 1 ' ; } else { descriptor [ 2 ] = ' 0 ' ; }
if ( ( layers - 1 ) & 0x02 ) { descriptor [ 3 ] = ' 1 ' ; } else { descriptor [ 3 ] = ' 0 ' ; }
if ( ( layers - 1 ) & 0x01 ) { descriptor [ 4 ] = ' 1 ' ; } else { descriptor [ 4 ] = ' 0 ' ; }
2008-09-03 00:01:41 +04:00
/* The next 11 bits represent the number of data blocks minus 1 */
2009-12-08 00:33:06 +03:00
if ( reader ) {
descriptor [ 5 ] = ' 1 ' ;
} else {
if ( ( data_blocks - 1 ) & 0x400 ) { descriptor [ 5 ] = ' 1 ' ; } else { descriptor [ 5 ] = ' 0 ' ; }
}
2008-11-08 02:42:53 +03:00
if ( ( data_blocks - 1 ) & 0x200 ) { descriptor [ 6 ] = ' 1 ' ; } else { descriptor [ 6 ] = ' 0 ' ; }
if ( ( data_blocks - 1 ) & 0x100 ) { descriptor [ 7 ] = ' 1 ' ; } else { descriptor [ 7 ] = ' 0 ' ; }
if ( ( data_blocks - 1 ) & 0x80 ) { descriptor [ 8 ] = ' 1 ' ; } else { descriptor [ 8 ] = ' 0 ' ; }
if ( ( data_blocks - 1 ) & 0x40 ) { descriptor [ 9 ] = ' 1 ' ; } else { descriptor [ 9 ] = ' 0 ' ; }
if ( ( data_blocks - 1 ) & 0x20 ) { descriptor [ 10 ] = ' 1 ' ; } else { descriptor [ 10 ] = ' 0 ' ; }
if ( ( data_blocks - 1 ) & 0x10 ) { descriptor [ 11 ] = ' 1 ' ; } else { descriptor [ 11 ] = ' 0 ' ; }
if ( ( data_blocks - 1 ) & 0x08 ) { descriptor [ 12 ] = ' 1 ' ; } else { descriptor [ 12 ] = ' 0 ' ; }
if ( ( data_blocks - 1 ) & 0x04 ) { descriptor [ 13 ] = ' 1 ' ; } else { descriptor [ 13 ] = ' 0 ' ; }
if ( ( data_blocks - 1 ) & 0x02 ) { descriptor [ 14 ] = ' 1 ' ; } else { descriptor [ 14 ] = ' 0 ' ; }
if ( ( data_blocks - 1 ) & 0x01 ) { descriptor [ 15 ] = ' 1 ' ; } else { descriptor [ 15 ] = ' 0 ' ; }
descriptor [ 16 ] = ' \0 ' ;
2010-04-06 13:14:28 +04:00
if ( debug ) printf ( " Mode Message = %s \n " , descriptor ) ;
2008-09-03 00:01:41 +04:00
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
/* Split into 4-bit codewords */
for ( i = 0 ; i < 4 ; i + + ) {
if ( descriptor [ i * 4 ] = = ' 1 ' ) { desc_data [ i ] + = 8 ; }
if ( descriptor [ ( i * 4 ) + 1 ] = = ' 1 ' ) { desc_data [ i ] + = 4 ; }
if ( descriptor [ ( i * 4 ) + 2 ] = = ' 1 ' ) { desc_data [ i ] + = 2 ; }
if ( descriptor [ ( i * 4 ) + 3 ] = = ' 1 ' ) { desc_data [ i ] + = 1 ; }
}
/* Add reed-solomon error correction with Galois field GF(16) and prime modulus
x ^ 4 + x + 1 ( section 7.2 .3 ) */
rs_init_gf ( 0x13 ) ;
if ( compact ) {
rs_init_code ( 5 , 1 ) ;
rs_encode ( 2 , desc_data , desc_ecc ) ;
for ( i = 0 ; i < 5 ; i + + ) {
2008-11-08 02:42:53 +03:00
if ( desc_ecc [ 4 - i ] & 0x08 ) { descriptor [ ( i * 4 ) + 8 ] = ' 1 ' ; } else { descriptor [ ( i * 4 ) + 8 ] = ' 0 ' ; }
if ( desc_ecc [ 4 - i ] & 0x04 ) { descriptor [ ( i * 4 ) + 9 ] = ' 1 ' ; } else { descriptor [ ( i * 4 ) + 9 ] = ' 0 ' ; }
if ( desc_ecc [ 4 - i ] & 0x02 ) { descriptor [ ( i * 4 ) + 10 ] = ' 1 ' ; } else { descriptor [ ( i * 4 ) + 10 ] = ' 0 ' ; }
if ( desc_ecc [ 4 - i ] & 0x01 ) { descriptor [ ( i * 4 ) + 11 ] = ' 1 ' ; } else { descriptor [ ( i * 4 ) + 11 ] = ' 0 ' ; }
2008-09-03 00:01:41 +04:00
}
} else {
rs_init_code ( 6 , 1 ) ;
rs_encode ( 4 , desc_data , desc_ecc ) ;
for ( i = 0 ; i < 6 ; i + + ) {
2008-11-08 02:42:53 +03:00
if ( desc_ecc [ 5 - i ] & 0x08 ) { descriptor [ ( i * 4 ) + 16 ] = ' 1 ' ; } else { descriptor [ ( i * 4 ) + 16 ] = ' 0 ' ; }
if ( desc_ecc [ 5 - i ] & 0x04 ) { descriptor [ ( i * 4 ) + 17 ] = ' 1 ' ; } else { descriptor [ ( i * 4 ) + 17 ] = ' 0 ' ; }
if ( desc_ecc [ 5 - i ] & 0x02 ) { descriptor [ ( i * 4 ) + 18 ] = ' 1 ' ; } else { descriptor [ ( i * 4 ) + 18 ] = ' 0 ' ; }
if ( desc_ecc [ 5 - i ] & 0x01 ) { descriptor [ ( i * 4 ) + 19 ] = ' 1 ' ; } else { descriptor [ ( i * 4 ) + 19 ] = ' 0 ' ; }
2008-09-03 00:01:41 +04:00
}
}
2008-10-12 22:52:54 +04:00
rs_free ( ) ;
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
/* Merge descriptor with the rest of the symbol */
for ( i = 0 ; i < 40 ; i + + ) {
if ( compact ) {
2008-11-08 02:42:53 +03:00
bit_pattern [ 2000 + i - 2 ] = descriptor [ i ] ;
2008-09-03 00:01:41 +04:00
} else {
2008-11-08 02:42:53 +03:00
bit_pattern [ 20000 + i - 2 ] = descriptor [ i ] ;
2008-09-03 00:01:41 +04:00
}
}
/* Plot all of the data into the symbol in pre-defined spiral pattern */
if ( compact ) {
2012-12-30 17:55:05 +04:00
2008-10-13 00:03:22 +04:00
for ( y = AztecCompactOffset [ layers - 1 ] ; y < ( 27 - AztecCompactOffset [ layers - 1 ] ) ; y + + ) {
for ( x = AztecCompactOffset [ layers - 1 ] ; x < ( 27 - AztecCompactOffset [ layers - 1 ] ) ; x + + ) {
2008-09-03 00:01:41 +04:00
if ( CompactAztecMap [ ( y * 27 ) + x ] = = 1 ) {
2009-06-01 00:33:54 +04:00
set_module ( symbol , y - AztecCompactOffset [ layers - 1 ] , x - AztecCompactOffset [ layers - 1 ] ) ;
2008-09-03 00:01:41 +04:00
}
if ( CompactAztecMap [ ( y * 27 ) + x ] > = 2 ) {
if ( bit_pattern [ CompactAztecMap [ ( y * 27 ) + x ] - 2 ] = = ' 1 ' ) {
2009-06-01 00:33:54 +04:00
set_module ( symbol , y - AztecCompactOffset [ layers - 1 ] , x - AztecCompactOffset [ layers - 1 ] ) ;
2008-09-03 00:01:41 +04:00
}
}
}
symbol - > row_height [ y - AztecCompactOffset [ layers - 1 ] ] = 1 ;
}
symbol - > rows = 27 - ( 2 * AztecCompactOffset [ layers - 1 ] ) ;
symbol - > width = 27 - ( 2 * AztecCompactOffset [ layers - 1 ] ) ;
} else {
2012-12-30 17:55:05 +04:00
2008-10-13 00:03:22 +04:00
for ( y = AztecOffset [ layers - 1 ] ; y < ( 151 - AztecOffset [ layers - 1 ] ) ; y + + ) {
for ( x = AztecOffset [ layers - 1 ] ; x < ( 151 - AztecOffset [ layers - 1 ] ) ; x + + ) {
2008-09-03 00:01:41 +04:00
if ( AztecMap [ ( y * 151 ) + x ] = = 1 ) {
2009-06-01 00:33:54 +04:00
set_module ( symbol , y - AztecOffset [ layers - 1 ] , x - AztecOffset [ layers - 1 ] ) ;
2008-09-03 00:01:41 +04:00
}
if ( AztecMap [ ( y * 151 ) + x ] > = 2 ) {
if ( bit_pattern [ AztecMap [ ( y * 151 ) + x ] - 2 ] = = ' 1 ' ) {
2009-06-01 00:33:54 +04:00
set_module ( symbol , y - AztecOffset [ layers - 1 ] , x - AztecOffset [ layers - 1 ] ) ;
2008-09-03 00:01:41 +04:00
}
}
}
symbol - > row_height [ y - AztecOffset [ layers - 1 ] ] = 1 ;
}
symbol - > rows = 151 - ( 2 * AztecOffset [ layers - 1 ] ) ;
symbol - > width = 151 - ( 2 * AztecOffset [ layers - 1 ] ) ;
}
2012-12-30 17:55:05 +04:00
2008-09-03 00:01:41 +04:00
return err_code ;
2008-09-26 15:39:06 +04:00
}
2008-11-09 13:06:05 +03:00
2009-09-29 13:45:46 +04:00
int aztec_runes ( struct zint_symbol * symbol , unsigned char source [ ] , int length )
2008-11-09 13:06:05 +03:00
{
2009-09-29 13:45:46 +04:00
int input_value , error_number , i , y , x ;
2008-11-09 13:06:05 +03:00
char binary_string [ 28 ] ;
unsigned char data_codewords [ 3 ] , ecc_codewords [ 6 ] ;
error_number = 0 ;
input_value = 0 ;
2009-09-29 13:45:46 +04:00
if ( length > 3 ) {
2008-11-09 13:06:05 +03:00
strcpy ( symbol - > errtxt , " Input too large " ) ;
return ERROR_INVALID_DATA ;
}
2009-10-06 23:03:00 +04:00
error_number = is_sane ( NEON , source , length ) ;
2008-11-09 13:06:05 +03:00
if ( error_number ! = 0 ) {
strcpy ( symbol - > errtxt , " Invalid characters in input " ) ;
return ERROR_INVALID_DATA ;
}
2009-09-29 13:45:46 +04:00
switch ( length ) {
2008-11-09 13:06:05 +03:00
case 3 : input_value = 100 * ctoi ( source [ 0 ] ) ;
input_value + = 10 * ctoi ( source [ 1 ] ) ;
input_value + = ctoi ( source [ 2 ] ) ;
break ;
case 2 : input_value = 10 * ctoi ( source [ 0 ] ) ;
input_value + = ctoi ( source [ 1 ] ) ;
break ;
case 1 : input_value = ctoi ( source [ 0 ] ) ;
break ;
}
2012-12-30 17:55:05 +04:00
2008-11-09 13:06:05 +03:00
if ( input_value > 255 ) {
strcpy ( symbol - > errtxt , " Input too large " ) ;
return ERROR_INVALID_DATA ;
}
2012-12-30 17:55:05 +04:00
2008-11-09 13:06:05 +03:00
strcpy ( binary_string , " " ) ;
if ( input_value & 0x80 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( input_value & 0x40 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( input_value & 0x20 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( input_value & 0x10 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( input_value & 0x08 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( input_value & 0x04 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( input_value & 0x02 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
if ( input_value & 0x01 ) { concat ( binary_string , " 1 " ) ; } else { concat ( binary_string , " 0 " ) ; }
data_codewords [ 0 ] = 0 ;
data_codewords [ 1 ] = 0 ;
for ( i = 0 ; i < 2 ; i + + ) {
if ( binary_string [ i * 4 ] = = ' 1 ' ) { data_codewords [ i ] + = 8 ; }
if ( binary_string [ ( i * 4 ) + 1 ] = = ' 1 ' ) { data_codewords [ i ] + = 4 ; }
if ( binary_string [ ( i * 4 ) + 2 ] = = ' 1 ' ) { data_codewords [ i ] + = 2 ; }
if ( binary_string [ ( i * 4 ) + 3 ] = = ' 1 ' ) { data_codewords [ i ] + = 1 ; }
}
2012-12-30 17:55:05 +04:00
2008-11-09 13:06:05 +03:00
rs_init_gf ( 0x13 ) ;
rs_init_code ( 5 , 1 ) ;
rs_encode ( 2 , data_codewords , ecc_codewords ) ;
rs_free ( ) ;
2012-12-30 17:55:05 +04:00
2008-11-09 13:06:05 +03:00
strcpy ( binary_string , " " ) ;
for ( i = 0 ; i < 5 ; i + + ) {
if ( ecc_codewords [ 4 - i ] & 0x08 ) { binary_string [ ( i * 4 ) + 8 ] = ' 1 ' ; } else { binary_string [ ( i * 4 ) + 8 ] = ' 0 ' ; }
if ( ecc_codewords [ 4 - i ] & 0x04 ) { binary_string [ ( i * 4 ) + 9 ] = ' 1 ' ; } else { binary_string [ ( i * 4 ) + 9 ] = ' 0 ' ; }
if ( ecc_codewords [ 4 - i ] & 0x02 ) { binary_string [ ( i * 4 ) + 10 ] = ' 1 ' ; } else { binary_string [ ( i * 4 ) + 10 ] = ' 0 ' ; }
if ( ecc_codewords [ 4 - i ] & 0x01 ) { binary_string [ ( i * 4 ) + 11 ] = ' 1 ' ; } else { binary_string [ ( i * 4 ) + 11 ] = ' 0 ' ; }
}
for ( i = 0 ; i < 28 ; i + = 2 ) {
if ( binary_string [ i ] = = ' 1 ' ) { binary_string [ i ] = ' 0 ' ; } else { binary_string [ i ] = ' 1 ' ; }
}
for ( y = 8 ; y < 19 ; y + + ) {
for ( x = 8 ; x < 19 ; x + + ) {
if ( CompactAztecMap [ ( y * 27 ) + x ] = = 1 ) {
2009-06-01 00:33:54 +04:00
set_module ( symbol , y - 8 , x - 8 ) ;
2008-11-09 13:06:05 +03:00
}
if ( CompactAztecMap [ ( y * 27 ) + x ] > = 2 ) {
if ( binary_string [ CompactAztecMap [ ( y * 27 ) + x ] - 2000 ] = = ' 1 ' ) {
2009-06-01 00:33:54 +04:00
set_module ( symbol , y - 8 , x - 8 ) ;
2008-11-09 13:06:05 +03:00
}
}
}
symbol - > row_height [ y - 8 ] = 1 ;
}
symbol - > rows = 11 ;
symbol - > width = 11 ;
2012-12-30 17:55:05 +04:00
2008-11-09 13:06:05 +03:00
return 0 ;
}