2009-07-05 00:48:42 +04:00
/* code1.c - USS Code One */
/*
libzint - the open source barcode library
2021-02-06 02:55:24 +03:00
Copyright ( C ) 2009 - 2021 Robin Stuart < rstuart114 @ gmail . com >
2009-07-05 00:48:42 +04:00
2013-05-16 21:26:38 +04:00
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
2017-10-23 22:37:52 +03:00
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2013-05-16 21:26:38 +04:00
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
2017-10-23 22:37:52 +03:00
documentation and / or other materials provided with the distribution .
2013-05-16 21:26:38 +04:00
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
2017-10-23 22:37:52 +03:00
without specific prior written permission .
2013-05-16 21:26:38 +04:00
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " 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 COPYRIGHT OWNER OR CONTRIBUTORS 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
2017-10-23 22:37:52 +03:00
OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
2013-05-16 21:26:38 +04:00
SUCH DAMAGE .
2016-02-20 12:38:03 +03:00
*/
2019-11-27 19:16:14 +03:00
/* vim: set ts=4 sw=4 et : */
2009-07-05 00:48:42 +04:00
# include "common.h"
# include "code1.h"
# include "reedsol.h"
2009-07-05 20:11:45 +04:00
# include "large.h"
2009-07-05 00:48:42 +04:00
# include <stdio.h>
2016-03-03 00:12:38 +03:00
# include <math.h>
2021-02-06 02:55:24 +03:00
# ifdef _MSC_VER
# include <malloc.h>
# endif
/* Add solid bar */
static void horiz ( struct zint_symbol * symbol , const int row_no , const int full ) {
2016-02-20 12:38:03 +03:00
int i ;
if ( full ) {
for ( i = 0 ; i < symbol - > width ; i + + ) {
set_module ( symbol , row_no , i ) ;
}
} else {
for ( i = 1 ; i < symbol - > width - 1 ; i + + ) {
set_module ( symbol , row_no , i ) ;
}
}
2009-07-05 00:48:42 +04:00
}
2021-02-06 02:55:24 +03:00
/* Central recognition pattern for Versions A-H */
static void central_finder ( struct zint_symbol * symbol , const int start_row , const int row_count ,
const int full_rows ) {
2016-02-20 12:38:03 +03:00
int i ;
for ( i = 0 ; i < row_count ; i + + ) {
if ( i < full_rows ) {
horiz ( symbol , start_row + ( i * 2 ) , 1 ) ;
} else {
horiz ( symbol , start_row + ( i * 2 ) , 0 ) ;
if ( i ! = row_count - 1 ) {
set_module ( symbol , start_row + ( i * 2 ) + 1 , 1 ) ;
set_module ( symbol , start_row + ( i * 2 ) + 1 , symbol - > width - 2 ) ;
}
}
}
2009-07-05 00:48:42 +04:00
}
2021-02-06 02:55:24 +03:00
/* Add solid column */
static void vert ( struct zint_symbol * symbol , const int column , const int height , const int top ) {
2016-02-20 12:38:03 +03:00
int i ;
if ( top ) {
for ( i = 0 ; i < height ; i + + ) {
set_module ( symbol , i , column ) ;
}
} else {
for ( i = 0 ; i < height ; i + + ) {
set_module ( symbol , symbol - > rows - i - 1 , column ) ;
}
}
2009-07-05 00:48:42 +04:00
}
2021-02-06 02:55:24 +03:00
/* Add bump to the right of the vertical recognition pattern column (Versions A-H) */
static void spigot ( struct zint_symbol * symbol , const int row_no ) {
2016-02-20 12:38:03 +03:00
int i ;
for ( i = symbol - > width - 1 ; i > 0 ; i - - ) {
if ( module_is_set ( symbol , row_no , i - 1 ) ) {
set_module ( symbol , row_no , i ) ;
}
}
2009-07-05 00:48:42 +04:00
}
2021-02-06 02:55:24 +03:00
/* Is basic (non-shifted) C40? */
static int isc40 ( const unsigned char input ) {
if ( ( input > = ' 0 ' & & input < = ' 9 ' ) | | ( input > = ' A ' & & input < = ' Z ' ) | | input = = ' ' ) {
return 1 ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
return 0 ;
2009-07-05 00:48:42 +04:00
}
2021-02-06 02:55:24 +03:00
/* Is basic (non-shifted) TEXT? */
static int istext ( const unsigned char input ) {
if ( ( input > = ' 0 ' & & input < = ' 9 ' ) | | ( input > = ' a ' & & input < = ' z ' ) | | input = = ' ' ) {
return 1 ;
}
return 0 ;
}
2012-12-30 17:55:05 +04:00
2021-02-06 02:55:24 +03:00
/* Is basic (non-shifted) C40/TEXT? */
static int isc40text ( const int current_mode , const unsigned char input ) {
return current_mode = = C1_C40 ? isc40 ( input ) : istext ( input ) ;
}
2012-12-30 17:55:05 +04:00
2021-02-06 02:55:24 +03:00
/* EDI characters are uppercase alphanumerics plus space plus EDI terminator (CR) plus 2 EDI separator chars */
static int isedi ( const unsigned char input ) {
2012-12-30 17:55:05 +04:00
2021-02-06 02:55:24 +03:00
if ( isc40 ( input ) ) {
2016-02-20 12:38:03 +03:00
return 1 ;
}
2021-02-06 02:55:24 +03:00
if ( input = = 13 | | input = = ' * ' | | input = = ' > ' ) {
2016-02-20 12:38:03 +03:00
return 1 ;
}
2021-02-06 02:55:24 +03:00
return 0 ;
}
/* Whether Step Q4bi applies, i.e. if one of the 3 EDI terminator/separator chars appears before a non-EDI char */
static int is_step_Q4bi_applicable ( const unsigned char source [ ] , const int sourcelen , const int position ) {
int i ;
for ( i = position ; i < sourcelen & & isedi ( source [ i ] ) ; i + + ) {
if ( source [ i ] = = 13 | | source [ i ] = = ' * ' | | source [ i ] = = ' > ' ) {
return 1 ;
}
2016-02-20 12:38:03 +03:00
}
2012-12-30 17:55:05 +04:00
2016-02-20 12:38:03 +03:00
return 0 ;
2009-07-05 00:48:42 +04:00
}
2021-06-30 00:02:24 +03:00
/* Character counts are multiplied by this, so as to be whole integer divisible by 2 and 3 */
# define C1_MULT 6
# define C1_MULT_1_DIV_2 3
# define C1_MULT_2_DIV_3 4
# define C1_MULT_1 6
# define C1_MULT_4_DIV_3 8
# define C1_MULT_2 12
# define C1_MULT_8_DIV_3 16
# define C1_MULT_3 18
# define C1_MULT_10_DIV_3 20
# define C1_MULT_13_DIV_3 26
# define C1_MULT_MINUS_1 5
# define C1_MULT_CEIL(n) ((((n) + C1_MULT_MINUS_1) / C1_MULT) * C1_MULT)
2021-02-06 02:55:24 +03:00
/* AIM USS Code One Annex D Steps J-R */
static int c1_look_ahead_test ( const unsigned char source [ ] , const int sourcelen , const int position ,
const int current_mode , const int gs1 ) {
2021-06-30 00:02:24 +03:00
int ascii_count , c40_count , text_count , edi_count , byte_count ;
2021-02-06 02:55:24 +03:00
int ascii_rnded , c40_rnded , text_rnded , edi_rnded , byte_rnded ;
2021-06-30 00:02:24 +03:00
int cnt_1 ;
2021-02-06 02:55:24 +03:00
int sp ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
/* Step J1 */
2016-02-20 12:38:03 +03:00
if ( current_mode = = C1_ASCII ) {
2021-06-30 00:02:24 +03:00
ascii_count = 0 ;
c40_count = C1_MULT_1 ;
text_count = C1_MULT_1 ;
edi_count = C1_MULT_1 ;
byte_count = C1_MULT_2 ;
2016-02-20 12:38:03 +03:00
} else {
2021-06-30 00:02:24 +03:00
ascii_count = C1_MULT_1 ;
c40_count = C1_MULT_2 ;
text_count = C1_MULT_2 ;
edi_count = C1_MULT_2 ;
byte_count = C1_MULT_3 ;
2016-02-20 12:38:03 +03:00
}
switch ( current_mode ) {
2021-06-30 00:02:24 +03:00
case C1_C40 : c40_count = 0 ; /* Step J2 */
2016-02-20 12:38:03 +03:00
break ;
2021-06-30 00:02:24 +03:00
case C1_TEXT : text_count = 0 ; /* Step J3 */
2016-02-20 12:38:03 +03:00
break ;
2021-06-30 00:02:24 +03:00
case C1_EDI : edi_count = 0 ; /* Missing in spec */
2016-02-20 12:38:03 +03:00
break ;
2021-06-30 00:02:24 +03:00
case C1_BYTE : byte_count = 0 ; /* Step J4 */
2016-02-20 12:38:03 +03:00
break ;
}
2021-02-06 02:55:24 +03:00
for ( sp = position ; sp < sourcelen ; sp + + ) {
2021-06-27 17:58:27 +03:00
unsigned char c = source [ sp ] ;
int is_extended = c & 0x80 ;
2016-02-20 12:38:03 +03:00
/* Step L */
2021-06-27 17:58:27 +03:00
if ( ( c > = ' 0 ' ) & & ( c < = ' 9 ' ) ) {
2021-06-30 00:02:24 +03:00
ascii_count + = C1_MULT_1_DIV_2 ; /* Step L1 */
2016-02-20 12:38:03 +03:00
} else {
2021-06-27 17:58:27 +03:00
if ( is_extended ) {
2021-06-30 00:02:24 +03:00
ascii_count = ceilf ( ascii_count ) + C1_MULT_2 ; /* Step L2 */
2016-02-20 12:38:03 +03:00
} else {
2021-06-30 00:02:24 +03:00
ascii_count = ceilf ( ascii_count ) + C1_MULT_1 ; /* Step L3 */
2016-02-20 12:38:03 +03:00
}
}
/* Step M */
2021-06-27 17:58:27 +03:00
if ( isc40 ( c ) ) {
2021-06-30 00:02:24 +03:00
c40_count + = C1_MULT_2_DIV_3 ; /* Step M1 */
2021-06-27 17:58:27 +03:00
} else if ( is_extended ) {
2021-06-30 00:02:24 +03:00
c40_count + = C1_MULT_8_DIV_3 ; /* Step M2 */
2021-02-06 02:55:24 +03:00
} else {
2021-06-30 00:02:24 +03:00
c40_count + = C1_MULT_4_DIV_3 ; /* Step M3 */
2016-02-20 12:38:03 +03:00
}
/* Step N */
2021-06-27 17:58:27 +03:00
if ( istext ( c ) ) {
2021-06-30 00:02:24 +03:00
text_count + = C1_MULT_2_DIV_3 ; /* Step N1 */
2021-06-27 17:58:27 +03:00
} else if ( is_extended ) {
2021-06-30 00:02:24 +03:00
text_count + = C1_MULT_8_DIV_3 ; /* Step N2 */
2021-02-06 02:55:24 +03:00
} else {
2021-06-30 00:02:24 +03:00
text_count + = C1_MULT_4_DIV_3 ; /* Step N3 */
2016-02-20 12:38:03 +03:00
}
/* Step O */
2021-06-27 17:58:27 +03:00
if ( isedi ( c ) ) {
2021-06-30 00:02:24 +03:00
edi_count + = C1_MULT_2_DIV_3 ; /* Step O1 */
2021-06-27 17:58:27 +03:00
} else if ( is_extended ) {
2021-06-30 00:02:24 +03:00
edi_count + = C1_MULT_13_DIV_3 ; /* Step O2 */
2016-02-20 12:38:03 +03:00
} else {
2021-06-30 00:02:24 +03:00
edi_count + = C1_MULT_10_DIV_3 ; /* Step O3 */
2016-02-20 12:38:03 +03:00
}
/* Step P */
2021-06-27 17:58:27 +03:00
if ( gs1 & & ( c = = ' [ ' ) ) {
2021-06-30 00:02:24 +03:00
byte_count + = C1_MULT_3 ; /* Step P1 */
2016-02-20 12:38:03 +03:00
} else {
2021-06-30 00:02:24 +03:00
byte_count + = C1_MULT_1 ; /* Step P2 */
2021-02-06 02:55:24 +03:00
}
2021-02-23 03:01:15 +03:00
/* If at least 4 characters processed */
2021-02-06 02:55:24 +03:00
/* NOTE: different than spec, where it's at least 3, but that ends up suppressing C40/TEXT/EDI.
2021-02-23 03:01:15 +03:00
BWIPP also uses 4 ( cf very similar Data Matrix ISO / IEC 16022 : 2006 Annex P algorithm ) */
if ( sp > = position + 3 ) {
2021-02-06 02:55:24 +03:00
/* Step Q */
2021-06-30 00:02:24 +03:00
ascii_rnded = C1_MULT_CEIL ( ascii_count ) ;
c40_rnded = C1_MULT_CEIL ( c40_count ) ;
text_rnded = C1_MULT_CEIL ( text_count ) ;
edi_rnded = C1_MULT_CEIL ( edi_count ) ;
byte_rnded = C1_MULT_CEIL ( byte_count ) ;
2021-02-06 02:55:24 +03:00
2021-06-30 00:02:24 +03:00
cnt_1 = byte_count + C1_MULT_1 ;
2021-06-27 17:58:27 +03:00
if ( cnt_1 < = ascii_rnded & & cnt_1 < = c40_rnded & & cnt_1 < = text_rnded & & cnt_1 < = edi_rnded ) {
2021-02-06 02:55:24 +03:00
return C1_BYTE ; /* Step Q1 */
}
2021-06-30 00:02:24 +03:00
cnt_1 = ascii_count + C1_MULT_1 ;
2021-06-27 17:58:27 +03:00
if ( cnt_1 < = c40_rnded & & cnt_1 < = text_rnded & & cnt_1 < = edi_rnded & & cnt_1 < = byte_rnded ) {
2021-02-06 02:55:24 +03:00
return C1_ASCII ; /* Step Q2 */
}
2021-06-30 00:02:24 +03:00
cnt_1 = text_rnded + C1_MULT_1 ;
2021-06-27 17:58:27 +03:00
if ( cnt_1 < = ascii_rnded & & cnt_1 < = c40_rnded & & cnt_1 < = edi_rnded & & cnt_1 < = byte_rnded ) {
2021-02-06 02:55:24 +03:00
return C1_TEXT ; /* Step Q3 */
}
2021-06-30 00:02:24 +03:00
cnt_1 = c40_rnded + C1_MULT_1 ;
2021-06-27 17:58:27 +03:00
if ( cnt_1 < = ascii_rnded & & cnt_1 < = text_rnded ) {
2021-02-06 02:55:24 +03:00
/* Step Q4 */
if ( c40_rnded < edi_rnded ) {
return C1_C40 ; /* Step Q4a */
}
if ( c40_rnded = = edi_rnded ) {
/* Step Q4b */
if ( is_step_Q4bi_applicable ( source , sourcelen , sp + 1 ) ) {
return C1_EDI ; /* Step Q4bi */
}
return C1_C40 ; /* Step Q4bii */
}
}
2021-06-30 00:02:24 +03:00
cnt_1 = edi_rnded + C1_MULT_1 ;
2021-06-27 17:58:27 +03:00
if ( cnt_1 < = ascii_rnded & & cnt_1 < = c40_rnded & & cnt_1 < = text_rnded & & cnt_1 < = byte_rnded ) {
2021-02-06 02:55:24 +03:00
return C1_EDI ; /* Step Q5 */
}
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
}
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
/* Step K */
2021-06-30 00:02:24 +03:00
ascii_rnded = C1_MULT_CEIL ( ascii_count ) ;
c40_rnded = C1_MULT_CEIL ( c40_count ) ;
text_rnded = C1_MULT_CEIL ( text_count ) ;
edi_rnded = C1_MULT_CEIL ( edi_count ) ;
byte_rnded = C1_MULT_CEIL ( byte_count ) ;
2021-02-06 02:55:24 +03:00
if ( byte_count < = ascii_rnded & & byte_count < = c40_rnded & & byte_count < = text_rnded & & byte_count < = edi_rnded ) {
return C1_BYTE ; /* Step K1 */
}
if ( ascii_count < = c40_rnded & & ascii_count < = text_rnded & & ascii_count < = edi_rnded
& & ascii_count < = byte_rnded ) {
return C1_ASCII ; /* Step K2 */
}
if ( c40_rnded < = text_rnded & & c40_rnded < = edi_rnded ) {
return C1_C40 ; /* Step K3 */
}
if ( text_rnded < = edi_rnded ) {
return C1_TEXT ; /* Step K4 */
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
return C1_EDI ; /* Step K5 */
}
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
/* Whether can fit last character or characters in a single ASCII codeword */
static int is_last_single_ascii ( const unsigned char string [ ] , const int length , const int sp ) {
2021-07-05 13:52:43 +03:00
if ( length - sp = = 1 & & string [ sp ] < = 127 ) {
2021-02-06 02:55:24 +03:00
return 1 ;
}
if ( length - sp = = 2 & & istwodigits ( string , length , sp ) ) {
return 1 ;
}
return 0 ;
}
2016-02-20 12:38:03 +03:00
2021-02-09 05:51:36 +03:00
/* Initialize number of digits array (taken from BWIPP) */
static void set_num_digits ( const unsigned char source [ ] , const int length , int * num_digits ) {
int i ;
for ( i = length - 1 ; i > = 0 ; i - - ) {
if ( source [ i ] > = ' 0 ' & & source [ i ] < = ' 9 ' ) {
num_digits [ i ] = num_digits [ i + 1 ] + 1 ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
}
}
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
/* Copy C40/TEXT/EDI triplets from buffer to target. Returns elements left in buffer (< 3) */
static int cte_buffer_transfer ( int cte_buffer [ 6 ] , int cte_p , unsigned target [ ] , int * p_tp ) {
int cte_i , cte_e ;
int tp = * p_tp ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
cte_e = ( cte_p / 3 ) * 3 ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
for ( cte_i = 0 ; cte_i < cte_e ; cte_i + = 3 ) {
int iv = ( 1600 * cte_buffer [ cte_i ] ) + ( 40 * cte_buffer [ cte_i + 1 ] ) + ( cte_buffer [ cte_i + 2 ] ) + 1 ;
target [ tp + + ] = iv > > 8 ;
target [ tp + + ] = iv & 0xFF ;
}
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
cte_p - = cte_e ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
if ( cte_p ) {
memmove ( cte_buffer , cte_buffer + cte_e , sizeof ( int ) * cte_p ) ;
}
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
* p_tp = tp ;
return cte_p ;
}
/* Copy DECIMAL bytes to target. Returns bits left in buffer (< 8) */
static int decimal_binary_transfer ( char decimal_binary [ 24 ] , int db_p , unsigned int target [ ] , int * p_tp ) {
int b_i , b_e , p ;
int tp = * p_tp ;
/* Transfer full bytes to target */
b_e = db_p & 0xF8 ;
for ( b_i = 0 ; b_i < b_e ; b_i + = 8 ) {
int value = 0 ;
for ( p = 0 ; p < 8 ; p + + ) {
value < < = 1 ;
value + = decimal_binary [ b_i + p ] = = ' 1 ' ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
target [ tp + + ] = value ;
}
db_p & = 0x07 ; /* Bits remaining */
if ( db_p ) {
memmove ( decimal_binary , decimal_binary + b_e , db_p ) ;
}
* p_tp = tp ;
return db_p ;
}
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
/* Unlatch to ASCII from DECIMAL mode using 6 ones flag. DECIMAL binary buffer will be empty */
static int decimal_unlatch ( char decimal_binary [ 24 ] , int db_p , unsigned int target [ ] , int * p_tp ,
const int decimal_count , const unsigned char * source , int * p_sp ) {
int sp = * p_sp ;
int bits_left ;
db_p = bin_append_posn ( 63 , 6 , decimal_binary , db_p ) ; /* Unlatch */
if ( db_p > = 8 ) {
db_p = decimal_binary_transfer ( decimal_binary , db_p , target , p_tp ) ;
}
bits_left = ( 8 - db_p ) & 0x07 ;
if ( decimal_count > = 1 & & bits_left > = 4 ) {
db_p = bin_append_posn ( ctoi ( source [ sp ] ) + 1 , 4 , decimal_binary , db_p ) ;
sp + + ;
if ( bits_left = = 6 ) {
db_p = bin_append_posn ( 1 , 2 , decimal_binary , db_p ) ;
2016-02-20 12:38:03 +03:00
}
2021-06-19 15:11:23 +03:00
( void ) decimal_binary_transfer ( decimal_binary , db_p , target , p_tp ) ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
} else if ( bits_left ) {
if ( bits_left > = 4 ) {
db_p = bin_append_posn ( 15 , 4 , decimal_binary , db_p ) ;
}
if ( bits_left = = 2 | | bits_left = = 6 ) {
db_p = bin_append_posn ( 1 , 2 , decimal_binary , db_p ) ;
2016-02-20 12:38:03 +03:00
}
2021-06-19 15:11:23 +03:00
( void ) decimal_binary_transfer ( decimal_binary , db_p , target , p_tp ) ;
2021-02-06 02:55:24 +03:00
}
* p_sp = sp ;
return 0 ;
}
/* Number of codewords remaining in a particular version (may be negative) */
2021-02-09 05:51:36 +03:00
static int codewords_remaining ( struct zint_symbol * symbol , const int tp ) {
2021-02-06 02:55:24 +03:00
int i ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
if ( symbol - > option_2 = = 10 ) { /* Version T */
if ( tp > 24 ) {
return 38 - tp ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
if ( tp > 10 ) {
return 24 - tp ;
}
return 10 - tp ;
}
/* Versions A to H */
for ( i = 6 ; i > = 0 ; i - - ) {
if ( tp > c1_data_length [ i ] ) {
return c1_data_length [ i + 1 ] - tp ;
}
}
return c1_data_length [ 0 ] - tp ;
}
/* Number of C40/TEXT elements needed to encode `input` */
static int c40text_cnt ( const int current_mode , const int gs1 , unsigned char input ) {
int cnt ;
if ( gs1 & & input = = ' [ ' ) {
return 2 ;
}
cnt = 1 ;
if ( ( current_mode = = C1_C40 & & c40_shift [ input ] ) | | ( current_mode = = C1_TEXT & & text_shift [ input ] ) ) {
cnt + = 1 ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
return cnt ;
2009-07-05 00:48:42 +04:00
}
2021-02-06 02:55:24 +03:00
/* Copy `source` to `eci_buf` with "\NNNNNN" ECI indicator at start and backslashes escaped */
2021-02-09 05:51:36 +03:00
static void eci_escape ( const int eci , unsigned char * source , const int length , unsigned char * eci_buf ,
const int eci_length ) {
2021-02-06 02:55:24 +03:00
int i , j ;
j = sprintf ( ( char * ) eci_buf , " \\ %06d " , eci ) ;
for ( i = 0 ; i < length & & j < eci_length ; i + + ) {
if ( source [ i ] = = ' \\ ' ) {
eci_buf [ j + + ] = ' \\ ' ;
}
eci_buf [ j + + ] = source [ i ] ;
}
eci_buf [ j ] = ' \0 ' ;
}
/* Convert to codewords */
static int c1_encode ( struct zint_symbol * symbol , unsigned char source [ ] , unsigned int target [ ] , int length ,
int * p_last_mode ) {
2016-02-20 12:38:03 +03:00
int current_mode , next_mode ;
2021-02-06 02:55:24 +03:00
int sp , tp , gs1 , i ;
int cte_buffer [ 6 ] , cte_p = 0 ; /* C1_C40/TEXT/EDI buffer and index */
char decimal_binary [ 24 ] ; /* C1_DECIMAL buffer */
int db_p = 0 ;
2016-02-20 12:38:03 +03:00
int byte_start = 0 ;
2021-02-06 02:55:24 +03:00
int debug_print = symbol - > debug & ZINT_DEBUG_PRINT ;
int eci_length = length + 7 + chr_cnt ( source , length , ' \\ ' ) ;
# ifndef _MSC_VER
unsigned char eci_buf [ eci_length + 1 ] ;
2021-02-09 05:51:36 +03:00
int num_digits [ eci_length + 1 ] ;
2021-02-06 02:55:24 +03:00
# else
unsigned char * eci_buf = ( unsigned char * ) _alloca ( eci_length + 1 ) ;
2021-02-09 05:51:36 +03:00
int * num_digits = ( int * ) _alloca ( sizeof ( int ) * ( eci_length + 1 ) ) ;
2021-02-06 02:55:24 +03:00
# endif
2016-02-20 12:38:03 +03:00
sp = 0 ;
tp = 0 ;
2021-02-09 05:51:36 +03:00
memset ( num_digits , 0 , sizeof ( int ) * ( eci_length + 1 ) ) ;
2021-02-06 02:55:24 +03:00
/* Step A */
current_mode = C1_ASCII ;
next_mode = C1_ASCII ;
2016-02-20 12:38:03 +03:00
2019-11-27 19:16:14 +03:00
if ( ( symbol - > input_mode & 0x07 ) = = GS1_MODE ) {
2016-02-20 12:38:03 +03:00
gs1 = 1 ;
} else {
gs1 = 0 ;
}
if ( gs1 ) {
2021-02-09 05:51:36 +03:00
set_num_digits ( source , length , num_digits ) ;
if ( length > = 15 & & num_digits [ 0 ] > = 15 ) {
2021-02-06 02:55:24 +03:00
target [ tp + + ] = 236 ; /* FNC1 and change to Decimal */
next_mode = C1_DECIMAL ;
2021-02-09 05:51:36 +03:00
} else if ( length > = 7 & & num_digits [ 0 ] = = length ) {
2021-02-06 02:55:24 +03:00
target [ tp + + ] = 236 ; /* FNC1 and change to Decimal */
next_mode = C1_DECIMAL ;
} else {
target [ tp + + ] = 232 ; /* FNC1 */
}
/* Note ignoring ECI if GS1 mode (up to caller to warn) */
2021-02-09 05:51:36 +03:00
} else {
if ( symbol - > eci ) {
target [ tp + + ] = 129 ; /* Pad */
target [ tp + + ] = ' \\ ' + 1 ; /* Escape char */
eci_escape ( symbol - > eci , source , length , eci_buf , eci_length ) ;
source = eci_buf ;
length = eci_length ;
}
set_num_digits ( source , length , num_digits ) ;
2016-03-03 00:12:38 +03:00
}
2016-02-20 12:38:03 +03:00
do {
if ( current_mode ! = next_mode ) {
/* Change mode */
switch ( next_mode ) {
2021-02-06 02:55:24 +03:00
case C1_C40 : target [ tp + + ] = 230 ;
2016-02-20 12:38:03 +03:00
break ;
2021-02-06 02:55:24 +03:00
case C1_TEXT : target [ tp + + ] = 239 ;
2016-02-20 12:38:03 +03:00
break ;
2021-02-06 02:55:24 +03:00
case C1_EDI : target [ tp + + ] = 238 ;
2016-02-20 12:38:03 +03:00
break ;
2021-02-06 02:55:24 +03:00
case C1_BYTE : target [ tp + + ] = 231 ;
byte_start = tp ;
target [ tp + + ] = 0 ; /* Byte count holder (may be expanded to 2 codewords) */
2016-02-20 12:38:03 +03:00
break ;
}
2021-02-06 02:55:24 +03:00
current_mode = next_mode ;
2016-02-20 12:38:03 +03:00
}
if ( current_mode = = C1_ASCII ) {
/* Step B - ASCII encodation */
next_mode = C1_ASCII ;
2021-02-09 05:51:36 +03:00
if ( ( length - sp ) > = 21 & & num_digits [ sp ] > = 21 ) {
2016-02-20 12:38:03 +03:00
/* Step B1 */
2021-02-06 02:55:24 +03:00
next_mode = C1_DECIMAL ;
db_p = bin_append_posn ( 15 , 4 , decimal_binary , db_p ) ;
2021-02-09 05:51:36 +03:00
} else if ( ( length - sp ) > = 13 & & num_digits [ sp ] = = ( length - sp ) ) {
2016-02-20 12:38:03 +03:00
/* Step B2 */
2021-02-06 02:55:24 +03:00
next_mode = C1_DECIMAL ;
db_p = bin_append_posn ( 15 , 4 , decimal_binary , db_p ) ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
if ( next_mode = = C1_ASCII ) {
2020-06-04 20:45:25 +03:00
if ( istwodigits ( source , length , sp ) ) {
2021-02-06 02:55:24 +03:00
if ( debug_print ) printf ( " ASCII double-digits " ) ;
/* Step B3 */
target [ tp + + ] = ( 10 * ctoi ( source [ sp ] ) ) + ctoi ( source [ sp + 1 ] ) + 130 ;
2016-02-20 12:38:03 +03:00
sp + = 2 ;
} else {
if ( ( gs1 ) & & ( source [ sp ] = = ' [ ' ) ) {
2021-02-09 05:51:36 +03:00
if ( length - ( sp + 1 ) > = 15 & & num_digits [ sp + 1 ] > = 15 ) {
2016-02-20 12:38:03 +03:00
/* Step B4 */
2021-02-06 02:55:24 +03:00
target [ tp + + ] = 236 ; /* FNC1 and change to Decimal */
sp + + ;
next_mode = C1_DECIMAL ;
2021-02-09 05:51:36 +03:00
} else if ( length - ( sp + 1 ) > = 7 & & num_digits [ sp + 1 ] = = length - ( sp + 1 ) ) {
2021-02-06 02:55:24 +03:00
/* Step B5 */
target [ tp + + ] = 236 ; /* FNC1 and change to Decimal */
sp + + ;
next_mode = C1_DECIMAL ;
2016-02-20 12:38:03 +03:00
}
}
if ( next_mode = = C1_ASCII ) {
/* Step B6 */
next_mode = c1_look_ahead_test ( source , length , sp , current_mode , gs1 ) ;
if ( next_mode = = C1_ASCII ) {
2021-02-06 02:55:24 +03:00
if ( debug_print ) printf ( " ASCII " ) ;
2021-06-27 17:58:27 +03:00
if ( source [ sp ] & 0x80 ) {
2016-02-20 12:38:03 +03:00
/* Step B7 */
2021-02-06 02:55:24 +03:00
target [ tp + + ] = 235 ; /* FNC4 (Upper Shift) */
target [ tp + + ] = ( source [ sp ] - 128 ) + 1 ;
} else if ( ( gs1 ) & & ( source [ sp ] = = ' [ ' ) ) {
/* Step B8 */
target [ tp + + ] = 232 ; /* FNC1 */
2016-02-20 12:38:03 +03:00
} else {
/* Step B8 */
2021-02-06 02:55:24 +03:00
target [ tp + + ] = source [ sp ] + 1 ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
sp + + ;
2016-02-20 12:38:03 +03:00
}
}
}
}
2021-02-06 02:55:24 +03:00
} else if ( current_mode = = C1_C40 | | current_mode = = C1_TEXT ) {
/* Step C/D - C40/TEXT encodation */
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
next_mode = current_mode ;
if ( cte_p = = 0 ) {
/* Step C/D1 */
2021-02-09 05:51:36 +03:00
if ( ( length - sp ) > = 12 & & num_digits [ sp ] > = 12 ) {
2021-02-06 02:55:24 +03:00
/* Step C/D1a */
next_mode = C1_ASCII ;
2021-02-09 05:51:36 +03:00
} else if ( ( length - sp ) > = 8 & & num_digits [ sp ] = = ( length - sp ) ) {
2021-02-06 02:55:24 +03:00
/* Step C/D1b */
next_mode = C1_ASCII ;
} else {
2016-02-20 12:38:03 +03:00
next_mode = c1_look_ahead_test ( source , length , sp , current_mode , gs1 ) ;
}
}
2021-02-06 02:55:24 +03:00
if ( next_mode ! = current_mode ) {
/* Step C/D1c */
target [ tp + + ] = 255 ; /* Unlatch */
2016-02-20 12:38:03 +03:00
} else {
2021-02-06 02:55:24 +03:00
/* Step C/D2 */
const char * ct_shift , * ct_value ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
if ( current_mode = = C1_C40 ) {
ct_shift = c40_shift ;
ct_value = c40_value ;
} else {
ct_shift = text_shift ;
ct_value = text_value ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
if ( debug_print ) printf ( current_mode = = C1_C40 ? " C40 " : " TEXT " ) ;
2016-02-20 12:38:03 +03:00
2021-06-27 17:58:27 +03:00
if ( source [ sp ] & 0x80 ) {
2021-02-06 02:55:24 +03:00
cte_buffer [ cte_p + + ] = 1 ; /* Shift 2 */
cte_buffer [ cte_p + + ] = 30 ; /* FNC4 (Upper Shift) */
if ( ct_shift [ source [ sp ] - 128 ] ) {
cte_buffer [ cte_p + + ] = ct_shift [ source [ sp ] - 128 ] - 1 ;
}
cte_buffer [ cte_p + + ] = ct_value [ source [ sp ] - 128 ] ;
} else if ( gs1 & & ( source [ sp ] = = ' [ ' ) ) {
cte_buffer [ cte_p + + ] = 1 ; /* Shift 2 */
cte_buffer [ cte_p + + ] = 27 ; /* FNC1 */
2016-02-20 12:38:03 +03:00
} else {
2021-02-06 02:55:24 +03:00
if ( ct_shift [ source [ sp ] ] ) {
cte_buffer [ cte_p + + ] = ct_shift [ source [ sp ] ] - 1 ;
}
cte_buffer [ cte_p + + ] = ct_value [ source [ sp ] ] ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
if ( cte_p > = 3 ) {
cte_p = cte_buffer_transfer ( cte_buffer , cte_p , target , & tp ) ;
2016-02-20 12:38:03 +03:00
}
sp + + ;
}
2021-02-06 02:55:24 +03:00
} else if ( current_mode = = C1_EDI ) {
2016-02-20 12:38:03 +03:00
/* Step E - EDI Encodation */
next_mode = C1_EDI ;
2021-02-06 02:55:24 +03:00
if ( cte_p = = 0 ) {
/* Step E1 */
2021-02-09 05:51:36 +03:00
if ( ( length - sp ) > = 12 & & num_digits [ sp ] > = 12 ) {
2021-02-06 02:55:24 +03:00
/* Step E1a */
next_mode = C1_ASCII ;
2021-02-09 05:51:36 +03:00
} else if ( ( length - sp ) > = 8 & & num_digits [ sp ] = = ( length - sp ) ) {
2021-02-06 02:55:24 +03:00
/* Step E1b */
next_mode = C1_ASCII ;
} else if ( ( length - sp ) < 3 | | ! isedi ( source [ sp ] ) | | ! isedi ( source [ sp + 1 ] )
| | ! isedi ( source [ sp + 2 ] ) ) {
/* Step E1c */
/* This ensures ASCII switch if don't have EDI triplet, so cte_p will be zero on loop exit */
2016-02-20 12:38:03 +03:00
next_mode = C1_ASCII ;
}
}
if ( next_mode ! = C1_EDI ) {
2021-02-06 02:55:24 +03:00
if ( is_last_single_ascii ( source , length , sp ) & & codewords_remaining ( symbol , tp ) = = 1 ) {
/* No unlatch needed if data fits as ASCII in last data codeword */
} else {
target [ tp + + ] = 255 ; /* Unlatch */
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
} else {
/* Step E2 */
static const char edi_nonalphanum_chars [ ] = " \015 *> " ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
if ( debug_print ) printf ( " EDI " ) ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
if ( ( source [ sp ] > = ' 0 ' ) & & ( source [ sp ] < = ' 9 ' ) ) {
cte_buffer [ cte_p + + ] = source [ sp ] - ' 0 ' + 4 ;
} else if ( ( source [ sp ] > = ' A ' ) & & ( source [ sp ] < = ' Z ' ) ) {
cte_buffer [ cte_p + + ] = source [ sp ] - ' A ' + 14 ;
} else {
cte_buffer [ cte_p + + ] = posn ( edi_nonalphanum_chars , source [ sp ] ) ;
}
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
if ( cte_p > = 3 ) {
cte_p = cte_buffer_transfer ( cte_buffer , cte_p , target , & tp ) ;
2016-02-20 12:38:03 +03:00
}
sp + + ;
}
2021-02-06 02:55:24 +03:00
} else if ( current_mode = = C1_DECIMAL ) {
2016-02-20 12:38:03 +03:00
/* Step F - Decimal encodation */
2021-02-06 02:55:24 +03:00
if ( debug_print ) printf ( " DECIMAL " ) ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
next_mode = C1_DECIMAL ;
2017-10-23 22:37:52 +03:00
2021-02-06 02:55:24 +03:00
if ( length - sp < 3 ) {
/* Step F1 */
int bits_left = 8 - db_p ;
2021-02-09 05:51:36 +03:00
int can_ascii = bits_left = = 8 & & is_last_single_ascii ( source , length , sp ) ;
if ( codewords_remaining ( symbol , tp ) = = 1 & & ( can_ascii | | ( num_digits [ sp ] = = 1 & & bits_left > = 4 ) ) ) {
if ( can_ascii ) {
2021-02-06 02:55:24 +03:00
/* Encode last character or last 2 digits as ASCII */
if ( istwodigits ( source , length , sp ) ) {
target [ tp + + ] = ( 10 * ctoi ( source [ sp ] ) ) + ctoi ( source [ sp + 1 ] ) + 130 ;
sp + = 2 ;
} else {
target [ tp + + ] = source [ sp ] + 1 ;
sp + + ;
2016-09-17 20:22:26 +03:00
}
2021-02-06 02:55:24 +03:00
} else {
/* Encode last digit in 4 bits */
db_p = bin_append_posn ( ctoi ( source [ sp ] ) + 1 , 4 , decimal_binary , db_p ) ;
sp + + ;
if ( bits_left = = 6 ) {
db_p = bin_append_posn ( 1 , 2 , decimal_binary , db_p ) ;
2016-09-17 20:22:26 +03:00
}
2021-02-06 02:55:24 +03:00
db_p = decimal_binary_transfer ( decimal_binary , db_p , target , & tp ) ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
} else {
2021-02-09 05:51:36 +03:00
db_p = decimal_unlatch ( decimal_binary , db_p , target , & tp , num_digits [ sp ] , source , & sp ) ;
2021-02-06 02:55:24 +03:00
current_mode = C1_ASCII ; /* Note need to set current_mode also in case exit loop */
2016-02-20 12:38:03 +03:00
}
next_mode = C1_ASCII ;
2021-02-06 02:55:24 +03:00
} else {
2021-02-09 05:51:36 +03:00
if ( num_digits [ sp ] < 3 ) {
2021-02-06 02:55:24 +03:00
/* Step F2 */
2021-02-09 05:51:36 +03:00
db_p = decimal_unlatch ( decimal_binary , db_p , target , & tp , num_digits [ sp ] , source , & sp ) ;
2021-02-06 02:55:24 +03:00
current_mode = next_mode = C1_ASCII ; /* Note need to set current_mode also in case exit loop */
} else {
/* Step F3 */
/* There are three digits - convert the value to binary */
int value = ( 100 * ctoi ( source [ sp ] ) ) + ( 10 * ctoi ( source [ sp + 1 ] ) ) + ctoi ( source [ sp + 2 ] ) + 1 ;
db_p = bin_append_posn ( value , 10 , decimal_binary , db_p ) ;
if ( db_p > = 8 ) {
db_p = decimal_binary_transfer ( decimal_binary , db_p , target , & tp ) ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
sp + = 3 ;
2016-02-20 12:38:03 +03:00
}
}
2021-02-06 02:55:24 +03:00
} else if ( current_mode = = C1_BYTE ) {
2016-02-20 12:38:03 +03:00
next_mode = C1_BYTE ;
if ( gs1 & & ( source [ sp ] = = ' [ ' ) ) {
next_mode = C1_ASCII ;
} else {
if ( source [ sp ] < = 127 ) {
next_mode = c1_look_ahead_test ( source , length , sp , current_mode , gs1 ) ;
}
}
if ( next_mode ! = C1_BYTE ) {
2021-02-06 02:55:24 +03:00
/* Update byte field length */
int byte_count = tp - ( byte_start + 1 ) ;
if ( byte_count < = 249 ) {
target [ byte_start ] = byte_count ;
2016-02-20 12:38:03 +03:00
} else {
2021-02-06 02:55:24 +03:00
/* Insert extra codeword */
memmove ( target + byte_start + 2 , target + byte_start + 1 , sizeof ( unsigned int ) * byte_count ) ;
target [ byte_start ] = 249 + ( byte_count / 250 ) ;
target [ byte_start + 1 ] = ( byte_count % 250 ) ;
tp + + ;
2016-02-20 12:38:03 +03:00
}
} else {
2021-02-06 02:55:24 +03:00
if ( debug_print ) printf ( " BYTE " ) ;
target [ tp + + ] = source [ sp ] ;
2016-02-20 12:38:03 +03:00
sp + + ;
}
}
if ( tp > 1480 ) {
2021-02-06 02:55:24 +03:00
if ( debug_print ) printf ( " \n " ) ;
2016-02-20 12:38:03 +03:00
/* Data is too large for symbol */
return 0 ;
}
} while ( sp < length ) ;
2021-02-06 02:55:24 +03:00
if ( debug_print ) {
printf ( " \n End Current Mode: %d, tp %d, cte_p %d, db_p %d \n " , current_mode , tp , cte_p , db_p ) ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
/* Empty buffers (note cte_buffer will be empty if current_mode C1_EDI) */
if ( current_mode = = C1_C40 | | current_mode = = C1_TEXT ) {
if ( cte_p > = 1 ) {
int cws_remaining = codewords_remaining ( symbol , tp ) ;
2021-08-05 18:34:45 +03:00
/* Note doing strict interpretation of spec here (same as BWIPP), as now also done in Data Matrix case */
2021-02-06 02:55:24 +03:00
if ( cws_remaining = = 1 & & cte_p = = 1 & & isc40text ( current_mode , source [ sp - 1 ] ) ) {
/* 2.2.2.2 "...except when a single symbol character is left at the end before the first
error correction character . This single character is encoded in the ASCII code set . " */
target [ tp + + ] = source [ sp - 1 ] + 1 ; /* As ASCII */
cte_p = 0 ;
} else if ( cws_remaining = = 2 & & cte_p = = 2 ) {
/* 2.2.2.2 "Two characters may be encoded in C40 mode in the last two data symbol characters of the
symbol as two C40 values followed by one of the C40 shift characters . " */
cte_buffer [ cte_p + + ] = 0 ; /* Shift 0 */
cte_p = cte_buffer_transfer ( cte_buffer , cte_p , target , & tp ) ;
}
if ( cte_p > = 1 ) {
int cnt , total_cnt = 0 ;
/* Backtrack to last complete triplet (same technique as BWIPP) */
while ( sp > 0 & & cte_p % 3 ) {
sp - - ;
cnt = c40text_cnt ( current_mode , gs1 , source [ sp ] ) ;
total_cnt + = cnt ;
cte_p - = cnt ;
}
tp - = ( total_cnt / 3 ) * 2 ;
target [ tp + + ] = 255 ; /* Unlatch */
for ( ; sp < length ; sp + + ) {
if ( istwodigits ( source , length , sp ) ) {
target [ tp + + ] = ( 10 * ctoi ( source [ sp ] ) ) + ctoi ( source [ sp + 1 ] ) + 130 ;
sp + + ;
2021-06-27 17:58:27 +03:00
} else if ( source [ sp ] & 0x80 ) {
2021-02-06 02:55:24 +03:00
target [ tp + + ] = 235 ; /* FNC4 (Upper Shift) */
target [ tp + + ] = ( source [ sp ] - 128 ) + 1 ;
} else if ( ( gs1 ) & & ( source [ sp ] = = ' [ ' ) ) {
target [ tp + + ] = 232 ; /* FNC1 */
} else {
target [ tp + + ] = source [ sp ] + 1 ;
}
}
current_mode = C1_ASCII ;
}
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
} else if ( current_mode = = C1_DECIMAL ) {
int bits_left ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
/* Finish Decimal mode and go back to ASCII unless only one codeword remaining */
if ( codewords_remaining ( symbol , tp ) > 1 ) {
db_p = bin_append_posn ( 63 , 6 , decimal_binary , db_p ) ; /* Unlatch */
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
if ( db_p > = 8 ) {
db_p = decimal_binary_transfer ( decimal_binary , db_p , target , & tp ) ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
bits_left = ( 8 - db_p ) & 0x07 ;
2017-10-23 22:37:52 +03:00
2021-02-06 02:55:24 +03:00
if ( bits_left ) {
2017-10-23 22:37:52 +03:00
2021-02-06 02:55:24 +03:00
if ( ( bits_left = = 4 ) | | ( bits_left = = 6 ) ) {
db_p = bin_append_posn ( 15 , 4 , decimal_binary , db_p ) ;
2016-02-20 12:38:03 +03:00
}
2017-10-23 22:37:52 +03:00
2021-02-06 02:55:24 +03:00
if ( bits_left = = 2 | | bits_left = = 6 ) {
db_p = bin_append_posn ( 1 , 2 , decimal_binary , db_p ) ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
2021-06-20 02:05:45 +03:00
( void ) decimal_binary_transfer ( decimal_binary , db_p , target , & tp ) ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
current_mode = C1_ASCII ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
} else if ( current_mode = = C1_BYTE ) {
/* Update byte field length unless no codewords remaining */
if ( codewords_remaining ( symbol , tp ) > 0 ) {
int byte_count = tp - ( byte_start + 1 ) ;
if ( byte_count < = 249 ) {
target [ byte_start ] = byte_count ;
} else {
/* Insert extra byte field byte */
memmove ( target + byte_start + 2 , target + byte_start + 1 , sizeof ( unsigned int ) * byte_count ) ;
target [ byte_start ] = 249 + ( byte_count / 250 ) ;
target [ byte_start + 1 ] = ( byte_count % 250 ) ;
tp + + ;
2016-02-20 12:38:03 +03:00
}
}
}
/* Re-check length of data */
if ( tp > 1480 ) {
/* Data is too large for symbol */
return 0 ;
}
2020-11-27 15:54:44 +03:00
2021-02-06 02:55:24 +03:00
* p_last_mode = current_mode ;
if ( debug_print ) {
printf ( " Target (%d): " , tp ) ;
2020-11-27 15:54:44 +03:00
for ( i = 0 ; i < tp ; i + + ) {
2021-07-07 15:58:04 +03:00
printf ( " [%d] " , ( int ) target [ i ] ) ;
2020-11-27 15:54:44 +03:00
}
2021-02-06 02:55:24 +03:00
printf ( " \n Last Mode: %d \n " , * p_last_mode ) ;
2016-02-20 12:38:03 +03:00
}
2020-11-27 15:54:44 +03:00
2016-02-20 12:38:03 +03:00
return tp ;
2009-07-05 00:48:42 +04:00
}
2021-02-06 02:55:24 +03:00
/* Set symbol from datagrid */
static void block_copy ( struct zint_symbol * symbol , char datagrid [ 136 ] [ 120 ] , const int start_row , const int start_col ,
const int height , const int width , const int row_offset , const int col_offset ) {
2016-02-20 12:38:03 +03:00
int i , j ;
for ( i = start_row ; i < ( start_row + height ) ; i + + ) {
for ( j = start_col ; j < ( start_col + width ) ; j + + ) {
2021-02-06 02:55:24 +03:00
if ( datagrid [ i ] [ j ] ) {
2016-02-20 12:38:03 +03:00
set_module ( symbol , i + row_offset , j + col_offset ) ;
}
}
}
2009-07-05 00:48:42 +04:00
}
2019-12-19 03:37:55 +03:00
INTERNAL int code_one ( struct zint_symbol * symbol , unsigned char source [ ] , int length ) {
2017-09-10 18:03:09 +03:00
int size = 1 , i , j ;
2016-02-20 12:38:03 +03:00
char datagrid [ 136 ] [ 120 ] ;
int row , col ;
int sub_version = 0 ;
2020-11-27 15:54:44 +03:00
rs_t rs ;
2021-02-06 02:55:24 +03:00
int error_number = 0 ;
2016-02-20 12:38:03 +03:00
if ( ( symbol - > option_2 < 0 ) | | ( symbol - > option_2 > 10 ) ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 513: Invalid symbol size " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_INVALID_OPTION ;
}
if ( symbol - > option_2 = = 9 ) {
/* Version S */
int codewords ;
2020-06-14 16:42:40 +03:00
large_int elreg ;
2021-02-06 02:55:24 +03:00
unsigned int data [ 30 ] , ecc [ 15 ] ;
2016-02-20 12:38:03 +03:00
int block_width ;
if ( length > 18 ) {
2021-02-06 02:55:24 +03:00
strcpy ( symbol - > errtxt , " 514: Input data too long for Version S " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_TOO_LONG ;
}
if ( is_sane ( NEON , source , length ) = = ZINT_ERROR_INVALID_DATA ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 515: Invalid input data (Version S encodes numeric input only) " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_INVALID_DATA ;
}
2021-02-06 02:55:24 +03:00
size = 9 ;
2016-02-20 12:38:03 +03:00
if ( length < = 6 ) {
/* Version S-10 */
sub_version = 1 ;
codewords = 4 ;
block_width = 2 ;
2021-02-06 02:55:24 +03:00
} else if ( length < = 12 ) {
/* Version S-20 */
sub_version = 2 ;
codewords = 8 ;
block_width = 4 ;
} else {
/* Version S-30 */
sub_version = 3 ;
codewords = 12 ;
block_width = 6 ;
2016-03-03 00:12:38 +03:00
}
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
if ( symbol - > debug & ZINT_DEBUG_PRINT ) {
printf ( " Subversion: %d \n " , sub_version ) ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
/* Convert value plus one to binary */
large_load_str_u64 ( & elreg , source , length ) ;
large_add_u64 ( & elreg , 1 ) ;
2020-06-14 16:42:40 +03:00
large_uint_array ( & elreg , data , codewords , 5 /*bits*/ ) ;
2016-02-20 12:38:03 +03:00
2020-11-27 15:54:44 +03:00
rs_init_gf ( & rs , 0x25 ) ;
2021-02-06 02:55:24 +03:00
rs_init_code ( & rs , codewords , 0 ) ;
2020-11-27 15:54:44 +03:00
rs_encode_uint ( & rs , codewords , data , ecc ) ;
2016-02-20 12:38:03 +03:00
for ( i = 0 ; i < codewords ; i + + ) {
2021-02-06 02:55:24 +03:00
data [ i + codewords ] = ecc [ codewords - i - 1 ] ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
if ( symbol - > debug & ZINT_DEBUG_PRINT ) {
printf ( " Codewords (%d): " , codewords ) ;
2021-07-07 15:58:04 +03:00
for ( i = 0 ; i < codewords * 2 ; i + + ) printf ( " %d " , ( int ) data [ i ] ) ;
2021-02-06 02:55:24 +03:00
printf ( " \n " ) ;
2016-02-20 12:38:03 +03:00
}
i = 0 ;
for ( row = 0 ; row < 2 ; row + + ) {
for ( col = 0 ; col < block_width ; col + + ) {
2021-02-06 02:55:24 +03:00
datagrid [ row * 2 ] [ col * 5 ] = data [ i ] & 0x10 ;
datagrid [ row * 2 ] [ ( col * 5 ) + 1 ] = data [ i ] & 0x08 ;
datagrid [ row * 2 ] [ ( col * 5 ) + 2 ] = data [ i ] & 0x04 ;
datagrid [ ( row * 2 ) + 1 ] [ col * 5 ] = data [ i ] & 0x02 ;
datagrid [ ( row * 2 ) + 1 ] [ ( col * 5 ) + 1 ] = data [ i ] & 0x01 ;
datagrid [ row * 2 ] [ ( col * 5 ) + 3 ] = data [ i + 1 ] & 0x10 ;
datagrid [ row * 2 ] [ ( col * 5 ) + 4 ] = data [ i + 1 ] & 0x08 ;
datagrid [ ( row * 2 ) + 1 ] [ ( col * 5 ) + 2 ] = data [ i + 1 ] & 0x04 ;
datagrid [ ( row * 2 ) + 1 ] [ ( col * 5 ) + 3 ] = data [ i + 1 ] & 0x02 ;
datagrid [ ( row * 2 ) + 1 ] [ ( col * 5 ) + 4 ] = data [ i + 1 ] & 0x01 ;
2016-02-20 12:38:03 +03:00
i + = 2 ;
}
}
symbol - > rows = 8 ;
symbol - > width = 10 * sub_version + 1 ;
2021-02-06 02:55:24 +03:00
} else if ( symbol - > option_2 = = 10 ) {
2016-02-20 12:38:03 +03:00
/* Version T */
2021-02-06 02:55:24 +03:00
unsigned int data [ 90 + 2 ] ; /* Allow for 90 BYTE mode (+ latch and byte count) */
2020-06-04 20:45:25 +03:00
unsigned int ecc [ 22 ] ;
2016-02-20 12:38:03 +03:00
int data_length ;
int data_cw , ecc_cw , block_width ;
2021-02-06 02:55:24 +03:00
int last_mode ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
if ( length > 90 | | ( symbol - > eci & & length + 7 + chr_cnt ( source , length , ' \\ ' ) > 90 ) ) {
strcpy ( symbol - > errtxt , " 519: Input data too long for Version T " ) ;
2020-06-04 20:45:25 +03:00
return ZINT_ERROR_TOO_LONG ;
2016-02-20 12:38:03 +03:00
}
2020-06-04 20:45:25 +03:00
2021-02-06 02:55:24 +03:00
data_length = c1_encode ( symbol , source , data , length , & last_mode ) ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
if ( data_length = = 0 | | data_length > 38 ) {
strcpy ( symbol - > errtxt , " 516: Input data too long for Version T " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_TOO_LONG ;
}
size = 10 ;
if ( data_length < = 10 ) {
sub_version = 1 ;
data_cw = 10 ;
ecc_cw = 10 ;
block_width = 4 ;
2021-02-06 02:55:24 +03:00
} else if ( data_length < = 24 ) {
sub_version = 2 ;
data_cw = 24 ;
ecc_cw = 16 ;
block_width = 8 ;
} else {
sub_version = 3 ;
data_cw = 38 ;
ecc_cw = 22 ;
block_width = 12 ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
if ( symbol - > debug & ZINT_DEBUG_PRINT ) {
printf ( " Padding: %d, Subversion: %d \n " , data_cw - data_length , sub_version ) ;
}
/* If require padding */
if ( data_cw > data_length ) {
/* If did not finish in ASCII or BYTE mode, switch to ASCII */
if ( last_mode ! = C1_ASCII & & last_mode ! = C1_BYTE ) {
data [ data_length + + ] = 255 ; /* Unlatch */
}
for ( i = data_length ; i < data_cw ; i + + ) {
data [ i ] = 129 ; /* Pad */
}
2016-02-20 12:38:03 +03:00
}
/* Calculate error correction data */
2020-11-27 15:54:44 +03:00
rs_init_gf ( & rs , 0x12d ) ;
2021-02-06 02:55:24 +03:00
rs_init_code ( & rs , ecc_cw , 0 ) ;
2020-11-27 15:54:44 +03:00
rs_encode_uint ( & rs , data_cw , data , ecc ) ;
2016-02-20 12:38:03 +03:00
for ( i = 0 ; i < ecc_cw ; i + + ) {
2021-02-06 02:55:24 +03:00
data [ data_cw + i ] = ecc [ ecc_cw - i - 1 ] ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
if ( symbol - > debug & ZINT_DEBUG_PRINT ) {
printf ( " Codewords (%d): " , data_cw + ecc_cw ) ;
2021-07-07 15:58:04 +03:00
for ( i = 0 ; i < data_cw + ecc_cw ; i + + ) printf ( " %d " , ( int ) data [ i ] ) ;
2021-02-06 02:55:24 +03:00
printf ( " \n " ) ;
2016-02-20 12:38:03 +03:00
}
i = 0 ;
for ( row = 0 ; row < 5 ; row + + ) {
for ( col = 0 ; col < block_width ; col + + ) {
2021-02-06 02:55:24 +03:00
datagrid [ row * 2 ] [ col * 4 ] = data [ i ] & 0x80 ;
datagrid [ row * 2 ] [ ( col * 4 ) + 1 ] = data [ i ] & 0x40 ;
datagrid [ row * 2 ] [ ( col * 4 ) + 2 ] = data [ i ] & 0x20 ;
datagrid [ row * 2 ] [ ( col * 4 ) + 3 ] = data [ i ] & 0x10 ;
datagrid [ ( row * 2 ) + 1 ] [ col * 4 ] = data [ i ] & 0x08 ;
datagrid [ ( row * 2 ) + 1 ] [ ( col * 4 ) + 1 ] = data [ i ] & 0x04 ;
datagrid [ ( row * 2 ) + 1 ] [ ( col * 4 ) + 2 ] = data [ i ] & 0x02 ;
datagrid [ ( row * 2 ) + 1 ] [ ( col * 4 ) + 3 ] = data [ i ] & 0x01 ;
2016-02-20 12:38:03 +03:00
i + + ;
}
}
symbol - > rows = 16 ;
symbol - > width = ( sub_version * 16 ) + 1 ;
2021-02-06 02:55:24 +03:00
} else {
/* Versions A to H */
unsigned int data [ 1480 + 560 ] ;
unsigned int sub_data [ 185 ] , sub_ecc [ 70 ] ;
2017-10-23 22:34:31 +03:00
int data_length ;
2021-02-06 02:55:24 +03:00
int data_cw ;
int blocks , data_blocks , ecc_blocks , ecc_length ;
int last_mode ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
data_length = c1_encode ( symbol , source , data , length , & last_mode ) ;
2016-02-20 12:38:03 +03:00
if ( data_length = = 0 ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 517: Input data is too long " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_TOO_LONG ;
}
for ( i = 7 ; i > = 0 ; i - - ) {
if ( c1_data_length [ i ] > = data_length ) {
size = i + 1 ;
}
}
if ( symbol - > option_2 > size ) {
size = symbol - > option_2 ;
}
2017-10-23 22:37:52 +03:00
2021-06-10 13:15:39 +03:00
if ( ( symbol - > option_2 ! = 0 ) & & ( symbol - > option_2 < size ) ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 518: Input too long for selected symbol size " ) ;
2017-04-11 11:26:39 +03:00
return ZINT_ERROR_TOO_LONG ;
}
2021-02-06 02:55:24 +03:00
data_cw = c1_data_length [ size - 1 ] ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
/* If require padding */
if ( data_cw > data_length ) {
/* If did not finish in ASCII or BYTE mode, switch to ASCII */
if ( last_mode ! = C1_ASCII & & last_mode ! = C1_BYTE ) {
data [ data_length + + ] = 255 ; /* Unlatch */
}
if ( symbol - > debug & ZINT_DEBUG_PRINT ) {
printf ( " Padding: %d \n " , data_cw - data_length ) ;
}
for ( i = data_length ; i < data_cw ; i + + ) {
data [ i ] = 129 ; /* Pad */
}
} else if ( symbol - > debug & ZINT_DEBUG_PRINT ) {
printf ( " No padding \n " ) ;
2016-02-20 12:38:03 +03:00
}
/* Calculate error correction data */
2021-02-06 02:55:24 +03:00
blocks = c1_blocks [ size - 1 ] ;
data_blocks = c1_data_blocks [ size - 1 ] ;
ecc_blocks = c1_ecc_blocks [ size - 1 ] ;
ecc_length = c1_ecc_length [ size - 1 ] ;
2016-02-20 12:38:03 +03:00
2020-11-27 15:54:44 +03:00
rs_init_gf ( & rs , 0x12d ) ;
2021-02-06 02:55:24 +03:00
rs_init_code ( & rs , ecc_blocks , 0 ) ;
for ( i = 0 ; i < blocks ; i + + ) {
for ( j = 0 ; j < data_blocks ; j + + ) {
sub_data [ j ] = data [ j * blocks + i ] ;
2016-02-20 12:38:03 +03:00
}
2021-02-06 02:55:24 +03:00
rs_encode_uint ( & rs , data_blocks , sub_data , sub_ecc ) ;
for ( j = 0 ; j < ecc_blocks ; j + + ) {
data [ data_cw + j * blocks + i ] = sub_ecc [ ecc_blocks - 1 - j ] ;
2016-02-20 12:38:03 +03:00
}
}
2021-02-06 02:55:24 +03:00
if ( symbol - > debug & ZINT_DEBUG_PRINT ) {
printf ( " Codewords (%d): " , data_cw + ecc_length ) ;
2021-07-07 15:58:04 +03:00
for ( i = 0 ; i < data_cw + ecc_length ; i + + ) printf ( " %d " , ( int ) data [ i ] ) ;
2021-02-06 02:55:24 +03:00
printf ( " \n " ) ;
2016-02-20 12:38:03 +03:00
}
i = 0 ;
for ( row = 0 ; row < c1_grid_height [ size - 1 ] ; row + + ) {
for ( col = 0 ; col < c1_grid_width [ size - 1 ] ; col + + ) {
2021-02-06 02:55:24 +03:00
datagrid [ row * 2 ] [ col * 4 ] = data [ i ] & 0x80 ;
datagrid [ row * 2 ] [ ( col * 4 ) + 1 ] = data [ i ] & 0x40 ;
datagrid [ row * 2 ] [ ( col * 4 ) + 2 ] = data [ i ] & 0x20 ;
datagrid [ row * 2 ] [ ( col * 4 ) + 3 ] = data [ i ] & 0x10 ;
datagrid [ ( row * 2 ) + 1 ] [ col * 4 ] = data [ i ] & 0x08 ;
datagrid [ ( row * 2 ) + 1 ] [ ( col * 4 ) + 1 ] = data [ i ] & 0x04 ;
datagrid [ ( row * 2 ) + 1 ] [ ( col * 4 ) + 2 ] = data [ i ] & 0x02 ;
datagrid [ ( row * 2 ) + 1 ] [ ( col * 4 ) + 3 ] = data [ i ] & 0x01 ;
2016-02-20 12:38:03 +03:00
i + + ;
}
}
symbol - > rows = c1_height [ size - 1 ] ;
symbol - > width = c1_width [ size - 1 ] ;
}
2021-02-06 02:55:24 +03:00
if ( symbol - > debug & ZINT_DEBUG_PRINT ) {
printf ( " Version: %d \n " , size ) ;
}
2016-02-20 12:38:03 +03:00
switch ( size ) {
case 1 : /* Version A */
central_finder ( symbol , 6 , 3 , 1 ) ;
vert ( symbol , 4 , 6 , 1 ) ;
vert ( symbol , 12 , 5 , 0 ) ;
set_module ( symbol , 5 , 12 ) ;
spigot ( symbol , 0 ) ;
spigot ( symbol , 15 ) ;
block_copy ( symbol , datagrid , 0 , 0 , 5 , 4 , 0 , 0 ) ;
block_copy ( symbol , datagrid , 0 , 4 , 5 , 12 , 0 , 2 ) ;
block_copy ( symbol , datagrid , 5 , 0 , 5 , 12 , 6 , 0 ) ;
block_copy ( symbol , datagrid , 5 , 12 , 5 , 4 , 6 , 2 ) ;
break ;
case 2 : /* Version B */
central_finder ( symbol , 8 , 4 , 1 ) ;
vert ( symbol , 4 , 8 , 1 ) ;
vert ( symbol , 16 , 7 , 0 ) ;
set_module ( symbol , 7 , 16 ) ;
spigot ( symbol , 0 ) ;
spigot ( symbol , 21 ) ;
block_copy ( symbol , datagrid , 0 , 0 , 7 , 4 , 0 , 0 ) ;
block_copy ( symbol , datagrid , 0 , 4 , 7 , 16 , 0 , 2 ) ;
block_copy ( symbol , datagrid , 7 , 0 , 7 , 16 , 8 , 0 ) ;
block_copy ( symbol , datagrid , 7 , 16 , 7 , 4 , 8 , 2 ) ;
break ;
case 3 : /* Version C */
central_finder ( symbol , 11 , 4 , 2 ) ;
vert ( symbol , 4 , 11 , 1 ) ;
vert ( symbol , 26 , 13 , 1 ) ;
vert ( symbol , 4 , 10 , 0 ) ;
vert ( symbol , 26 , 10 , 0 ) ;
spigot ( symbol , 0 ) ;
spigot ( symbol , 27 ) ;
block_copy ( symbol , datagrid , 0 , 0 , 10 , 4 , 0 , 0 ) ;
block_copy ( symbol , datagrid , 0 , 4 , 10 , 20 , 0 , 2 ) ;
block_copy ( symbol , datagrid , 0 , 24 , 10 , 4 , 0 , 4 ) ;
block_copy ( symbol , datagrid , 10 , 0 , 10 , 4 , 8 , 0 ) ;
block_copy ( symbol , datagrid , 10 , 4 , 10 , 20 , 8 , 2 ) ;
block_copy ( symbol , datagrid , 10 , 24 , 10 , 4 , 8 , 4 ) ;
break ;
case 4 : /* Version D */
central_finder ( symbol , 16 , 5 , 1 ) ;
vert ( symbol , 4 , 16 , 1 ) ;
vert ( symbol , 20 , 16 , 1 ) ;
vert ( symbol , 36 , 16 , 1 ) ;
vert ( symbol , 4 , 15 , 0 ) ;
vert ( symbol , 20 , 15 , 0 ) ;
vert ( symbol , 36 , 15 , 0 ) ;
spigot ( symbol , 0 ) ;
spigot ( symbol , 12 ) ;
spigot ( symbol , 27 ) ;
spigot ( symbol , 39 ) ;
block_copy ( symbol , datagrid , 0 , 0 , 15 , 4 , 0 , 0 ) ;
block_copy ( symbol , datagrid , 0 , 4 , 15 , 14 , 0 , 2 ) ;
block_copy ( symbol , datagrid , 0 , 18 , 15 , 14 , 0 , 4 ) ;
block_copy ( symbol , datagrid , 0 , 32 , 15 , 4 , 0 , 6 ) ;
block_copy ( symbol , datagrid , 15 , 0 , 15 , 4 , 10 , 0 ) ;
block_copy ( symbol , datagrid , 15 , 4 , 15 , 14 , 10 , 2 ) ;
block_copy ( symbol , datagrid , 15 , 18 , 15 , 14 , 10 , 4 ) ;
block_copy ( symbol , datagrid , 15 , 32 , 15 , 4 , 10 , 6 ) ;
break ;
case 5 : /* Version E */
central_finder ( symbol , 22 , 5 , 2 ) ;
vert ( symbol , 4 , 22 , 1 ) ;
vert ( symbol , 26 , 24 , 1 ) ;
vert ( symbol , 48 , 22 , 1 ) ;
vert ( symbol , 4 , 21 , 0 ) ;
vert ( symbol , 26 , 21 , 0 ) ;
vert ( symbol , 48 , 21 , 0 ) ;
spigot ( symbol , 0 ) ;
spigot ( symbol , 12 ) ;
spigot ( symbol , 39 ) ;
spigot ( symbol , 51 ) ;
block_copy ( symbol , datagrid , 0 , 0 , 21 , 4 , 0 , 0 ) ;
block_copy ( symbol , datagrid , 0 , 4 , 21 , 20 , 0 , 2 ) ;
block_copy ( symbol , datagrid , 0 , 24 , 21 , 20 , 0 , 4 ) ;
block_copy ( symbol , datagrid , 0 , 44 , 21 , 4 , 0 , 6 ) ;
block_copy ( symbol , datagrid , 21 , 0 , 21 , 4 , 10 , 0 ) ;
block_copy ( symbol , datagrid , 21 , 4 , 21 , 20 , 10 , 2 ) ;
block_copy ( symbol , datagrid , 21 , 24 , 21 , 20 , 10 , 4 ) ;
block_copy ( symbol , datagrid , 21 , 44 , 21 , 4 , 10 , 6 ) ;
break ;
case 6 : /* Version F */
central_finder ( symbol , 31 , 5 , 3 ) ;
vert ( symbol , 4 , 31 , 1 ) ;
vert ( symbol , 26 , 35 , 1 ) ;
vert ( symbol , 48 , 31 , 1 ) ;
vert ( symbol , 70 , 35 , 1 ) ;
vert ( symbol , 4 , 30 , 0 ) ;
vert ( symbol , 26 , 30 , 0 ) ;
vert ( symbol , 48 , 30 , 0 ) ;
vert ( symbol , 70 , 30 , 0 ) ;
spigot ( symbol , 0 ) ;
spigot ( symbol , 12 ) ;
spigot ( symbol , 24 ) ;
spigot ( symbol , 45 ) ;
spigot ( symbol , 57 ) ;
spigot ( symbol , 69 ) ;
block_copy ( symbol , datagrid , 0 , 0 , 30 , 4 , 0 , 0 ) ;
block_copy ( symbol , datagrid , 0 , 4 , 30 , 20 , 0 , 2 ) ;
block_copy ( symbol , datagrid , 0 , 24 , 30 , 20 , 0 , 4 ) ;
block_copy ( symbol , datagrid , 0 , 44 , 30 , 20 , 0 , 6 ) ;
block_copy ( symbol , datagrid , 0 , 64 , 30 , 4 , 0 , 8 ) ;
block_copy ( symbol , datagrid , 30 , 0 , 30 , 4 , 10 , 0 ) ;
block_copy ( symbol , datagrid , 30 , 4 , 30 , 20 , 10 , 2 ) ;
block_copy ( symbol , datagrid , 30 , 24 , 30 , 20 , 10 , 4 ) ;
block_copy ( symbol , datagrid , 30 , 44 , 30 , 20 , 10 , 6 ) ;
block_copy ( symbol , datagrid , 30 , 64 , 30 , 4 , 10 , 8 ) ;
break ;
case 7 : /* Version G */
central_finder ( symbol , 47 , 6 , 2 ) ;
vert ( symbol , 6 , 47 , 1 ) ;
vert ( symbol , 27 , 49 , 1 ) ;
vert ( symbol , 48 , 47 , 1 ) ;
vert ( symbol , 69 , 49 , 1 ) ;
vert ( symbol , 90 , 47 , 1 ) ;
vert ( symbol , 6 , 46 , 0 ) ;
vert ( symbol , 27 , 46 , 0 ) ;
vert ( symbol , 48 , 46 , 0 ) ;
vert ( symbol , 69 , 46 , 0 ) ;
vert ( symbol , 90 , 46 , 0 ) ;
spigot ( symbol , 0 ) ;
spigot ( symbol , 12 ) ;
spigot ( symbol , 24 ) ;
spigot ( symbol , 36 ) ;
spigot ( symbol , 67 ) ;
spigot ( symbol , 79 ) ;
spigot ( symbol , 91 ) ;
spigot ( symbol , 103 ) ;
block_copy ( symbol , datagrid , 0 , 0 , 46 , 6 , 0 , 0 ) ;
block_copy ( symbol , datagrid , 0 , 6 , 46 , 19 , 0 , 2 ) ;
block_copy ( symbol , datagrid , 0 , 25 , 46 , 19 , 0 , 4 ) ;
block_copy ( symbol , datagrid , 0 , 44 , 46 , 19 , 0 , 6 ) ;
block_copy ( symbol , datagrid , 0 , 63 , 46 , 19 , 0 , 8 ) ;
block_copy ( symbol , datagrid , 0 , 82 , 46 , 6 , 0 , 10 ) ;
block_copy ( symbol , datagrid , 46 , 0 , 46 , 6 , 12 , 0 ) ;
block_copy ( symbol , datagrid , 46 , 6 , 46 , 19 , 12 , 2 ) ;
block_copy ( symbol , datagrid , 46 , 25 , 46 , 19 , 12 , 4 ) ;
block_copy ( symbol , datagrid , 46 , 44 , 46 , 19 , 12 , 6 ) ;
block_copy ( symbol , datagrid , 46 , 63 , 46 , 19 , 12 , 8 ) ;
block_copy ( symbol , datagrid , 46 , 82 , 46 , 6 , 12 , 10 ) ;
break ;
case 8 : /* Version H */
central_finder ( symbol , 69 , 6 , 3 ) ;
vert ( symbol , 6 , 69 , 1 ) ;
vert ( symbol , 26 , 73 , 1 ) ;
vert ( symbol , 46 , 69 , 1 ) ;
vert ( symbol , 66 , 73 , 1 ) ;
vert ( symbol , 86 , 69 , 1 ) ;
vert ( symbol , 106 , 73 , 1 ) ;
vert ( symbol , 126 , 69 , 1 ) ;
vert ( symbol , 6 , 68 , 0 ) ;
vert ( symbol , 26 , 68 , 0 ) ;
vert ( symbol , 46 , 68 , 0 ) ;
vert ( symbol , 66 , 68 , 0 ) ;
vert ( symbol , 86 , 68 , 0 ) ;
vert ( symbol , 106 , 68 , 0 ) ;
vert ( symbol , 126 , 68 , 0 ) ;
spigot ( symbol , 0 ) ;
spigot ( symbol , 12 ) ;
spigot ( symbol , 24 ) ;
spigot ( symbol , 36 ) ;
spigot ( symbol , 48 ) ;
spigot ( symbol , 60 ) ;
spigot ( symbol , 87 ) ;
spigot ( symbol , 99 ) ;
spigot ( symbol , 111 ) ;
spigot ( symbol , 123 ) ;
spigot ( symbol , 135 ) ;
spigot ( symbol , 147 ) ;
block_copy ( symbol , datagrid , 0 , 0 , 68 , 6 , 0 , 0 ) ;
block_copy ( symbol , datagrid , 0 , 6 , 68 , 18 , 0 , 2 ) ;
block_copy ( symbol , datagrid , 0 , 24 , 68 , 18 , 0 , 4 ) ;
block_copy ( symbol , datagrid , 0 , 42 , 68 , 18 , 0 , 6 ) ;
block_copy ( symbol , datagrid , 0 , 60 , 68 , 18 , 0 , 8 ) ;
block_copy ( symbol , datagrid , 0 , 78 , 68 , 18 , 0 , 10 ) ;
block_copy ( symbol , datagrid , 0 , 96 , 68 , 18 , 0 , 12 ) ;
block_copy ( symbol , datagrid , 0 , 114 , 68 , 6 , 0 , 14 ) ;
block_copy ( symbol , datagrid , 68 , 0 , 68 , 6 , 12 , 0 ) ;
block_copy ( symbol , datagrid , 68 , 6 , 68 , 18 , 12 , 2 ) ;
block_copy ( symbol , datagrid , 68 , 24 , 68 , 18 , 12 , 4 ) ;
block_copy ( symbol , datagrid , 68 , 42 , 68 , 18 , 12 , 6 ) ;
block_copy ( symbol , datagrid , 68 , 60 , 68 , 18 , 12 , 8 ) ;
block_copy ( symbol , datagrid , 68 , 78 , 68 , 18 , 12 , 10 ) ;
block_copy ( symbol , datagrid , 68 , 96 , 68 , 18 , 12 , 12 ) ;
block_copy ( symbol , datagrid , 68 , 114 , 68 , 6 , 12 , 14 ) ;
break ;
case 9 : /* Version S */
horiz ( symbol , 5 , 1 ) ;
horiz ( symbol , 7 , 1 ) ;
set_module ( symbol , 6 , 0 ) ;
set_module ( symbol , 6 , symbol - > width - 1 ) ;
unset_module ( symbol , 7 , 1 ) ;
unset_module ( symbol , 7 , symbol - > width - 2 ) ;
switch ( sub_version ) {
case 1 : /* Version S-10 */
set_module ( symbol , 0 , 5 ) ;
block_copy ( symbol , datagrid , 0 , 0 , 4 , 5 , 0 , 0 ) ;
block_copy ( symbol , datagrid , 0 , 5 , 4 , 5 , 0 , 1 ) ;
break ;
case 2 : /* Version S-20 */
set_module ( symbol , 0 , 10 ) ;
set_module ( symbol , 4 , 10 ) ;
block_copy ( symbol , datagrid , 0 , 0 , 4 , 10 , 0 , 0 ) ;
block_copy ( symbol , datagrid , 0 , 10 , 4 , 10 , 0 , 1 ) ;
break ;
case 3 : /* Version S-30 */
set_module ( symbol , 0 , 15 ) ;
set_module ( symbol , 4 , 15 ) ;
set_module ( symbol , 6 , 15 ) ;
block_copy ( symbol , datagrid , 0 , 0 , 4 , 15 , 0 , 0 ) ;
block_copy ( symbol , datagrid , 0 , 15 , 4 , 15 , 0 , 1 ) ;
break ;
}
break ;
case 10 : /* Version T */
horiz ( symbol , 11 , 1 ) ;
horiz ( symbol , 13 , 1 ) ;
horiz ( symbol , 15 , 1 ) ;
set_module ( symbol , 12 , 0 ) ;
set_module ( symbol , 12 , symbol - > width - 1 ) ;
set_module ( symbol , 14 , 0 ) ;
set_module ( symbol , 14 , symbol - > width - 1 ) ;
unset_module ( symbol , 13 , 1 ) ;
unset_module ( symbol , 13 , symbol - > width - 2 ) ;
unset_module ( symbol , 15 , 1 ) ;
unset_module ( symbol , 15 , symbol - > width - 2 ) ;
switch ( sub_version ) {
case 1 : /* Version T-16 */
set_module ( symbol , 0 , 8 ) ;
set_module ( symbol , 10 , 8 ) ;
block_copy ( symbol , datagrid , 0 , 0 , 10 , 8 , 0 , 0 ) ;
block_copy ( symbol , datagrid , 0 , 8 , 10 , 8 , 0 , 1 ) ;
break ;
case 2 : /* Version T-32 */
set_module ( symbol , 0 , 16 ) ;
set_module ( symbol , 10 , 16 ) ;
set_module ( symbol , 12 , 16 ) ;
block_copy ( symbol , datagrid , 0 , 0 , 10 , 16 , 0 , 0 ) ;
block_copy ( symbol , datagrid , 0 , 16 , 10 , 16 , 0 , 1 ) ;
break ;
case 3 : /* Verion T-48 */
set_module ( symbol , 0 , 24 ) ;
set_module ( symbol , 10 , 24 ) ;
set_module ( symbol , 12 , 24 ) ;
set_module ( symbol , 14 , 24 ) ;
block_copy ( symbol , datagrid , 0 , 0 , 10 , 24 , 0 , 0 ) ;
block_copy ( symbol , datagrid , 0 , 24 , 10 , 24 , 0 , 1 ) ;
break ;
}
break ;
}
for ( i = 0 ; i < symbol - > rows ; i + + ) {
symbol - > row_height [ i ] = 1 ;
}
2021-06-19 15:11:23 +03:00
symbol - > height = symbol - > rows ;
2016-02-20 12:38:03 +03:00
2021-02-06 02:55:24 +03:00
if ( symbol - > option_2 = = 9 ) { /* Version S */
if ( symbol - > eci | | ( symbol - > input_mode & 0x07 ) = = GS1_MODE ) {
strcpy ( symbol - > errtxt , " 511: ECI and GS1 mode ignored for Version S " ) ;
error_number = ZINT_WARN_INVALID_OPTION ;
}
} else if ( symbol - > eci & & ( symbol - > input_mode & 0x07 ) = = GS1_MODE ) {
strcpy ( symbol - > errtxt , " 512: ECI ignored for GS1 mode " ) ;
error_number = ZINT_WARN_INVALID_OPTION ;
}
return error_number ;
2009-07-05 00:48:42 +04:00
}