2018-02-06 20:57:01 +00:00
/* mailmark.c - Royal Mail 4-state Mailmark barcodes */
/*
libzint - the open source barcode library
2021-06-10 11:15:39 +01:00
Copyright ( C ) 2008 - 2021 Robin Stuart < rstuart114 @ gmail . com >
2018-02-06 20:57:01 +00:00
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
documentation and / or other materials provided with the distribution .
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission .
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
OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE .
*/
2019-12-19 00:37:55 +00:00
/* vim: set ts=4 sw=4 et : */
2018-02-06 20:57:01 +00:00
2021-06-10 11:15:39 +01:00
/*
2018-02-06 20:57:01 +00:00
* Developed in accordance with " Royal Mail Mailmark barcode C encoding and deconding instructions "
* ( https : //www.royalmail.com/sites/default/files/Mailmark-4-state-barcode-C-encoding-and-decoding-instructions-Sept-2015.pdf)
* and " Royal Mail Mailmark barcode L encoding and decoding "
* ( https : //www.royalmail.com/sites/default/files/Mailmark-4-state-barcode-L-encoding-and-decoding-instructions-Sept-2015.pdf)
2021-06-10 11:15:39 +01:00
*
2018-02-06 20:57:01 +00:00
*/
# include <stdio.h>
# ifdef _MSC_VER
# include <malloc.h>
# endif
# include "common.h"
# include "large.h"
# include "reedsol.h"
2021-07-06 19:53:31 +01:00
# define RUBIDIUM "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ "
2018-02-06 20:57:01 +00:00
// Allowed character values from Table 3
# define SET_F "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
# define SET_L "ABDEFGHJLNPQRSTUWXYZ"
# define SET_N "0123456789"
# define SET_S " "
static const char * postcode_format [ 6 ] = {
" FNFNLLNLS " , " FFNNLLNLS " , " FFNNNLLNL " , " FFNFNLLNL " , " FNNLLNLSS " , " FNNNLLNLS "
} ;
// Data/Check Symbols from Table 5
2020-12-23 10:57:24 +00:00
static const unsigned char data_symbol_odd [ 32 ] = {
2018-02-06 20:57:01 +00:00
0x01 , 0x02 , 0x04 , 0x07 , 0x08 , 0x0B , 0x0D , 0x0E , 0x10 , 0x13 , 0x15 , 0x16 ,
0x19 , 0x1A , 0x1C , 0x1F , 0x20 , 0x23 , 0x25 , 0x26 , 0x29 , 0x2A , 0x2C , 0x2F ,
0x31 , 0x32 , 0x34 , 0x37 , 0x38 , 0x3B , 0x3D , 0x3E
} ;
2020-12-23 10:57:24 +00:00
static const unsigned char data_symbol_even [ 30 ] = {
2018-02-06 20:57:01 +00:00
0x03 , 0x05 , 0x06 , 0x09 , 0x0A , 0x0C , 0x0F , 0x11 , 0x12 , 0x14 , 0x17 , 0x18 ,
0x1B , 0x1D , 0x1E , 0x21 , 0x22 , 0x24 , 0x27 , 0x28 , 0x2B , 0x2D , 0x2E , 0x30 ,
0x33 , 0x35 , 0x36 , 0x39 , 0x3A , 0x3C
} ;
static const unsigned short extender_group_c [ 22 ] = {
3 , 5 , 7 , 11 , 13 , 14 , 16 , 17 , 19 , 0 , 1 , 2 , 4 , 6 , 8 , 9 , 10 , 12 , 15 , 18 , 20 , 21
} ;
static const unsigned short extender_group_l [ 26 ] = {
2 , 5 , 7 , 8 , 13 , 14 , 15 , 16 , 21 , 22 , 23 , 0 , 1 , 3 , 4 , 6 , 9 , 10 , 11 , 12 , 17 , 18 , 19 , 20 , 24 , 25
} ;
2019-12-19 00:37:55 +00:00
static int verify_character ( char input , char type ) {
2018-02-06 20:57:01 +00:00
int val = 0 ;
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
switch ( type ) {
case ' F ' :
val = posn ( SET_F , input ) ;
break ;
case ' L ' :
val = posn ( SET_L , input ) ;
break ;
case ' N ' :
val = posn ( SET_N , input ) ;
break ;
case ' S ' :
val = posn ( SET_S , input ) ;
break ;
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
if ( val = = - 1 ) {
return 0 ;
} else {
return 1 ;
}
}
2021-08-10 12:04:25 +01:00
static int verify_postcode ( char * postcode , int type ) {
2018-02-06 20:57:01 +00:00
int i ;
char pattern [ 11 ] ;
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
strcpy ( pattern , postcode_format [ type - 1 ] ) ;
for ( i = 0 ; i < 9 ; i + + ) {
if ( ! ( verify_character ( postcode [ i ] , pattern [ i ] ) ) ) {
return 1 ;
}
}
return 0 ;
}
2021-06-19 13:11:23 +01:00
INTERNAL int daft_set_height ( struct zint_symbol * symbol , float min_height , float max_height ) ;
2018-02-06 20:57:01 +00:00
/* Royal Mail Mailmark */
2020-12-23 10:57:24 +00:00
INTERNAL int mailmark ( struct zint_symbol * symbol , unsigned char source [ ] , int length ) {
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
char local_source [ 28 ] ;
int format ;
int version_id ;
2018-03-30 09:46:54 +01:00
int mail_class ;
2018-02-06 20:57:01 +00:00
int supply_chain_id ;
2021-06-10 11:15:39 +01:00
unsigned int item_id ;
2018-02-06 20:57:01 +00:00
char postcode [ 10 ] ;
int postcode_type ;
char pattern [ 10 ] ;
2020-06-14 14:42:40 +01:00
large_int destination_postcode ;
large_int b ;
large_int cdv ;
2018-04-06 10:50:19 +01:00
unsigned char data [ 26 ] ;
2018-02-06 20:57:01 +00:00
int data_top , data_step ;
unsigned char check [ 7 ] ;
2021-06-10 11:15:39 +01:00
unsigned int extender [ 27 ] ;
2018-02-06 20:57:01 +00:00
char bar [ 80 ] ;
int check_count ;
2020-05-21 18:22:28 +01:00
int i , j , len ;
2020-11-27 12:54:44 +00:00
rs_t rs ;
2021-06-19 13:11:23 +01:00
int error_number = 0 ;
2021-06-10 11:15:39 +01:00
2018-02-10 07:26:33 +00:00
if ( length > 26 ) {
2021-07-06 19:53:31 +01:00
strcpy ( symbol - > errtxt , " 580: Input too long (26 character maximum) " ) ;
2018-02-10 07:26:33 +00:00
return ZINT_ERROR_TOO_LONG ;
2018-02-06 20:57:01 +00:00
}
2021-06-10 11:15:39 +01:00
2021-08-10 12:04:25 +01:00
ustrcpy ( local_source , source ) ;
2021-06-10 11:15:39 +01:00
2018-02-10 07:26:33 +00:00
if ( length < 22 ) {
for ( i = length ; i < = 22 ; i + + ) {
strcat ( local_source , " " ) ;
}
length = 22 ;
}
2021-06-10 11:15:39 +01:00
2018-02-10 07:26:33 +00:00
if ( ( length > 22 ) & & ( length < 26 ) ) {
for ( i = length ; i < = 26 ; i + + ) {
strcat ( local_source , " " ) ;
}
length = 26 ;
2021-06-10 11:15:39 +01:00
}
2021-08-10 12:04:25 +01:00
to_upper ( ( unsigned char * ) local_source ) ;
2021-06-10 11:15:39 +01:00
2020-06-14 14:42:40 +01:00
if ( symbol - > debug & ZINT_DEBUG_PRINT ) {
2018-02-06 20:57:01 +00:00
printf ( " Producing Mailmark %s \n " , local_source ) ;
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
if ( is_sane ( RUBIDIUM , ( unsigned char * ) local_source , length ) ! = 0 ) {
2021-07-06 19:53:31 +01:00
strcpy ( symbol - > errtxt , " 581: Invalid character in data (alphanumerics and space only) " ) ;
2018-02-06 20:57:01 +00:00
return ZINT_ERROR_INVALID_DATA ;
}
// Format is in the range 0-4
format = ctoi ( local_source [ 0 ] ) ;
if ( ( format < 0 ) | | ( format > 4 ) ) {
2021-07-06 19:53:31 +01:00
strcpy ( symbol - > errtxt , " 582: Format out of range (0 to 4) " ) ;
2018-02-06 20:57:01 +00:00
return ZINT_ERROR_INVALID_DATA ;
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
// Version ID is in the range 1-4
version_id = ctoi ( local_source [ 1 ] ) - 1 ;
if ( ( version_id < 0 ) | | ( version_id > 3 ) ) {
2021-07-06 19:53:31 +01:00
strcpy ( symbol - > errtxt , " 583: Version ID out of range (1 to 4) " ) ;
2018-02-06 20:57:01 +00:00
return ZINT_ERROR_INVALID_DATA ;
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
// Class is in the range 0-9,A-E
2018-03-30 09:46:54 +01:00
mail_class = ctoi ( local_source [ 2 ] ) ;
if ( ( mail_class < 0 ) | | ( mail_class > 14 ) ) {
2021-07-06 19:53:31 +01:00
strcpy ( symbol - > errtxt , " 584: Class out of range (0 to 9 and A to E) " ) ;
2018-02-06 20:57:01 +00:00
return ZINT_ERROR_INVALID_DATA ;
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
// Supply Chain ID is 2 digits for barcode C and 6 digits for barcode L
supply_chain_id = 0 ;
for ( i = 3 ; i < ( length - 17 ) ; i + + ) {
if ( ( local_source [ i ] > = ' 0 ' ) & & ( local_source [ i ] < = ' 9 ' ) ) {
supply_chain_id * = 10 ;
supply_chain_id + = ctoi ( local_source [ i ] ) ;
} else {
2021-07-06 19:53:31 +01:00
strcpy ( symbol - > errtxt , " 585: Invalid Supply Chain ID (digits only) " ) ;
2018-02-06 20:57:01 +00:00
return ZINT_ERROR_INVALID_DATA ;
}
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
// Item ID is 8 digits
item_id = 0 ;
for ( i = length - 17 ; i < ( length - 9 ) ; i + + ) {
if ( ( local_source [ i ] > = ' 0 ' ) & & ( local_source [ i ] < = ' 9 ' ) ) {
item_id * = 10 ;
2021-06-10 11:15:39 +01:00
item_id + = ctoi ( local_source [ i ] ) ;
2018-02-06 20:57:01 +00:00
} else {
2021-07-06 19:53:31 +01:00
strcpy ( symbol - > errtxt , " 586: Invalid Item ID (digits only) " ) ;
2018-02-06 20:57:01 +00:00
return ZINT_ERROR_INVALID_DATA ;
}
}
2021-06-10 11:15:39 +01:00
2018-04-09 21:46:20 +01:00
// Separate Destination Post Code plus DPS field
2018-02-06 20:57:01 +00:00
for ( i = 0 ; i < 9 ; i + + ) {
postcode [ i ] = local_source [ ( length - 9 ) + i ] ;
}
postcode [ 9 ] = ' \0 ' ;
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
// Detect postcode type
2021-06-10 11:15:39 +01:00
/* postcode_type is used to select which format of postcode
*
2018-02-06 20:57:01 +00:00
* 1 = FNFNLLNLS
* 2 = FFNNLLNLS
* 3 = FFNNNLLNL
* 4 = FFNFNLLNL
* 5 = FNNLLNLSS
* 6 = FNNNLLNLS
* 7 = International designation
*/
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
if ( strcmp ( postcode , " XY11 " ) = = 0 ) {
postcode_type = 7 ;
} else {
if ( postcode [ 7 ] = = ' ' ) {
postcode_type = 5 ;
} else {
if ( postcode [ 8 ] = = ' ' ) {
// Types 1, 2 and 6
if ( ( postcode [ 1 ] > = ' 0 ' ) & & ( postcode [ 1 ] < = ' 9 ' ) ) {
if ( ( postcode [ 2 ] > = ' 0 ' ) & & ( postcode [ 2 ] < = ' 9 ' ) ) {
postcode_type = 6 ;
} else {
postcode_type = 1 ;
}
} else {
postcode_type = 2 ;
}
} else {
// Types 3 and 4
if ( ( postcode [ 3 ] > = ' 0 ' ) & & ( postcode [ 3 ] < = ' 9 ' ) ) {
postcode_type = 3 ;
} else {
postcode_type = 4 ;
}
}
}
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
// Verify postcode type
if ( postcode_type ! = 7 ) {
if ( verify_postcode ( postcode , postcode_type ) ! = 0 ) {
2018-02-09 20:55:17 +00:00
strcpy ( symbol - > errtxt , " 587: Invalid postcode " ) ;
2018-02-06 20:57:01 +00:00
return ZINT_ERROR_INVALID_DATA ;
}
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
// Convert postcode to internal user field
2020-06-14 14:42:40 +01:00
large_load_u64 ( & destination_postcode , 0 ) ;
2018-02-06 20:57:01 +00:00
if ( postcode_type ! = 7 ) {
strcpy ( pattern , postcode_format [ postcode_type - 1 ] ) ;
2020-06-14 14:42:40 +01:00
large_load_u64 ( & b , 0 ) ;
2018-02-06 20:57:01 +00:00
for ( i = 0 ; i < 9 ; i + + ) {
switch ( pattern [ i ] ) {
case ' F ' :
2020-06-14 14:42:40 +01:00
large_mul_u64 ( & b , 26 ) ;
large_add_u64 ( & b , posn ( SET_F , postcode [ i ] ) ) ;
2018-02-06 20:57:01 +00:00
break ;
case ' L ' :
2020-06-14 14:42:40 +01:00
large_mul_u64 ( & b , 20 ) ;
large_add_u64 ( & b , posn ( SET_L , postcode [ i ] ) ) ;
2018-02-06 20:57:01 +00:00
break ;
case ' N ' :
2020-06-14 14:42:40 +01:00
large_mul_u64 ( & b , 10 ) ;
large_add_u64 ( & b , posn ( SET_N , postcode [ i ] ) ) ;
2018-02-06 20:57:01 +00:00
break ;
2020-06-14 14:42:40 +01:00
// case 'S' ignored as value is 0
2018-02-06 20:57:01 +00:00
}
}
2020-06-14 14:42:40 +01:00
large_load ( & destination_postcode , & b ) ;
2018-04-09 21:46:20 +01:00
// destination_postcode = a + b
2020-06-14 14:42:40 +01:00
large_load_u64 ( & b , 1 ) ;
2018-02-06 20:57:01 +00:00
if ( postcode_type = = 1 ) {
2020-06-14 14:42:40 +01:00
large_add ( & destination_postcode , & b ) ;
2018-02-06 20:57:01 +00:00
}
2020-06-14 14:42:40 +01:00
large_add_u64 ( & b , 5408000000 ) ;
2018-02-06 20:57:01 +00:00
if ( postcode_type = = 2 ) {
2020-06-14 14:42:40 +01:00
large_add ( & destination_postcode , & b ) ;
2018-02-06 20:57:01 +00:00
}
2020-06-14 14:42:40 +01:00
large_add_u64 ( & b , 5408000000 ) ;
2018-02-06 20:57:01 +00:00
if ( postcode_type = = 3 ) {
2020-06-14 14:42:40 +01:00
large_add ( & destination_postcode , & b ) ;
2018-02-06 20:57:01 +00:00
}
2020-06-14 14:42:40 +01:00
large_add_u64 ( & b , 54080000000 ) ;
2018-02-06 20:57:01 +00:00
if ( postcode_type = = 4 ) {
2020-06-14 14:42:40 +01:00
large_add ( & destination_postcode , & b ) ;
2018-02-06 20:57:01 +00:00
}
2020-06-14 14:42:40 +01:00
large_add_u64 ( & b , 140608000000 ) ;
2018-02-06 20:57:01 +00:00
if ( postcode_type = = 5 ) {
2020-06-14 14:42:40 +01:00
large_add ( & destination_postcode , & b ) ;
2018-02-06 20:57:01 +00:00
}
2020-06-14 14:42:40 +01:00
large_add_u64 ( & b , 208000000 ) ;
2018-02-06 20:57:01 +00:00
if ( postcode_type = = 6 ) {
2020-06-14 14:42:40 +01:00
large_add ( & destination_postcode , & b ) ;
2018-02-06 20:57:01 +00:00
}
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
// Conversion from Internal User Fields to Consolidated Data Value
// Set CDV to 0
2020-06-14 14:42:40 +01:00
large_load_u64 ( & cdv , 0 ) ;
2018-02-06 20:57:01 +00:00
// Add Destination Post Code plus DPS
2020-06-14 14:42:40 +01:00
large_add ( & cdv , & destination_postcode ) ;
2018-02-06 20:57:01 +00:00
// Multiply by 100,000,000
2020-06-14 14:42:40 +01:00
large_mul_u64 ( & cdv , 100000000 ) ;
2018-02-06 20:57:01 +00:00
// Add Item ID
2020-06-14 14:42:40 +01:00
large_add_u64 ( & cdv , item_id ) ;
2021-06-10 11:15:39 +01:00
if ( length = = 22 ) {
2018-02-06 20:57:01 +00:00
// Barcode C - Multiply by 100
2020-06-14 14:42:40 +01:00
large_mul_u64 ( & cdv , 100 ) ;
2018-02-06 20:57:01 +00:00
} else {
// Barcode L - Multiply by 1,000,000
2020-06-14 14:42:40 +01:00
large_mul_u64 ( & cdv , 1000000 ) ;
2018-02-06 20:57:01 +00:00
}
2020-06-14 14:42:40 +01:00
2018-02-06 20:57:01 +00:00
// Add Supply Chain ID
2020-06-14 14:42:40 +01:00
large_add_u64 ( & cdv , supply_chain_id ) ;
2018-02-06 20:57:01 +00:00
// Multiply by 15
2020-06-14 14:42:40 +01:00
large_mul_u64 ( & cdv , 15 ) ;
2018-02-06 20:57:01 +00:00
// Add Class
2020-06-14 14:42:40 +01:00
large_add_u64 ( & cdv , mail_class ) ;
2018-02-06 20:57:01 +00:00
// Multiply by 5
2020-06-14 14:42:40 +01:00
large_mul_u64 ( & cdv , 5 ) ;
2018-02-06 20:57:01 +00:00
// Add Format
2020-06-14 14:42:40 +01:00
large_add_u64 ( & cdv , format ) ;
2018-02-06 20:57:01 +00:00
// Multiply by 4
2020-06-14 14:42:40 +01:00
large_mul_u64 ( & cdv , 4 ) ;
2018-02-06 20:57:01 +00:00
// Add Version ID
2020-06-14 14:42:40 +01:00
large_add_u64 ( & cdv , version_id ) ;
if ( symbol - > debug & ZINT_DEBUG_PRINT ) {
2018-02-06 20:57:01 +00:00
printf ( " DPC type %d \n " , postcode_type ) ;
printf ( " CDV: " ) ;
2020-06-14 14:42:40 +01:00
large_print ( & cdv ) ;
2018-02-06 20:57:01 +00:00
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
if ( length = = 22 ) {
data_top = 15 ;
data_step = 8 ;
check_count = 6 ;
} else {
data_top = 18 ;
data_step = 10 ;
check_count = 7 ;
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
// Conversion from Consolidated Data Value to Data Numbers
2020-06-14 14:42:40 +01:00
for ( j = data_top ; j > = ( data_step + 1 ) ; j - - ) {
2020-12-23 10:57:24 +00:00
data [ j ] = ( unsigned char ) large_div_u64 ( & cdv , 32 ) ;
2018-02-06 20:57:01 +00:00
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
for ( j = data_step ; j > = 0 ; j - - ) {
2020-12-23 10:57:24 +00:00
data [ j ] = ( unsigned char ) large_div_u64 ( & cdv , 30 ) ;
2018-02-06 20:57:01 +00:00
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
// Generation of Reed-Solomon Check Numbers
2020-11-27 12:54:44 +00:00
rs_init_gf ( & rs , 0x25 ) ;
rs_init_code ( & rs , check_count , 1 ) ;
rs_encode ( & rs , ( data_top + 1 ) , data , check ) ;
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
// Append check digits to data
for ( i = 1 ; i < = check_count ; i + + ) {
data [ data_top + i ] = check [ check_count - i ] ;
}
2021-06-10 11:15:39 +01:00
2020-06-14 14:42:40 +01:00
if ( symbol - > debug & ZINT_DEBUG_PRINT ) {
2018-02-06 20:57:01 +00:00
printf ( " Codewords: " ) ;
for ( i = 0 ; i < = data_top + check_count ; i + + ) {
printf ( " %d " , ( int ) data [ i ] ) ;
}
printf ( " \n " ) ;
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
// Conversion from Data Numbers and Check Numbers to Data Symbols and Check Symbols
for ( i = 0 ; i < = data_step ; i + + ) {
data [ i ] = data_symbol_even [ data [ i ] ] ;
}
for ( i = data_step + 1 ; i < = ( data_top + check_count ) ; i + + ) {
data [ i ] = data_symbol_odd [ data [ i ] ] ;
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
// Conversion from Data Symbols and Check Symbols to Extender Groups
for ( i = 0 ; i < length ; i + + ) {
if ( length = = 22 ) {
extender [ extender_group_c [ i ] ] = data [ i ] ;
} else {
extender [ extender_group_l [ i ] ] = data [ i ] ;
}
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
// Conversion from Extender Groups to Bar Identifiers
strcpy ( bar , " " ) ;
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
for ( i = 0 ; i < length ; i + + ) {
for ( j = 0 ; j < 3 ; j + + ) {
2021-06-10 11:15:39 +01:00
switch ( extender [ i ] & 0x24 ) {
2018-02-06 20:57:01 +00:00
case 0x24 :
strcat ( bar , " F " ) ;
break ;
case 0x20 :
if ( i % 2 ) {
strcat ( bar , " D " ) ;
} else {
strcat ( bar , " A " ) ;
}
break ;
case 0x04 :
if ( i % 2 ) {
strcat ( bar , " A " ) ;
} else {
strcat ( bar , " D " ) ;
}
break ;
default :
strcat ( bar , " T " ) ;
break ;
}
extender [ i ] = extender [ i ] < < 1 ;
}
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
bar [ ( length * 3 ) ] = ' \0 ' ;
2021-06-10 11:15:39 +01:00
2020-06-14 14:42:40 +01:00
if ( symbol - > debug & ZINT_DEBUG_PRINT ) {
2018-02-06 20:57:01 +00:00
printf ( " Bar pattern: %s \n " , bar ) ;
}
2021-06-10 11:15:39 +01:00
2018-02-06 20:57:01 +00:00
/* Translate 4-state data pattern to symbol */
j = 0 ;
2020-12-23 10:57:24 +00:00
for ( i = 0 , len = ( int ) strlen ( bar ) ; i < len ; i + + ) {
2018-02-06 20:57:01 +00:00
if ( ( bar [ i ] = = ' F ' ) | | ( bar [ i ] = = ' A ' ) ) {
set_module ( symbol , 0 , j ) ;
}
set_module ( symbol , 1 , j ) ;
if ( ( bar [ i ] = = ' F ' ) | | ( bar [ i ] = = ' D ' ) ) {
set_module ( symbol , 2 , j ) ;
}
j + = 2 ;
}
2021-06-19 13:11:23 +01:00
# ifdef COMPLIANT_HEIGHTS
/* Royal Mail Mailmark Barcode Definition Document (15 Sept 2015) Section 3.5.1
https : //www.royalmail.com/sites/default/files/Royal-Mail-Mailmark-barcode-definition-document-September-2015.pdf
Using bar pitch as X ( 25.4 mm / 42.3 ) ~ 0.6 mm based on 21.2 bars + 21.1 spaces per 25.4 mm ( bar width 0.38 - 63 mm )
Using recommended 1.9 mm and 1.3 mm heights for Ascender / Descenders and Trackers resp . as defaults
Min height 4.22 mm * 39 ( max pitch ) / 25.4 mm ~ 6.47 , max height 5.84 mm * 47 ( min pitch ) / 25.4 mm ~ 10.8
*/
symbol - > row_height [ 0 ] = ( float ) ( ( 1.9 * 42.3 ) / 25.4 ) ; /* ~3.16 */
symbol - > row_height [ 1 ] = ( float ) ( ( 1.3 * 42.3 ) / 25.4 ) ; /* ~2.16 */
/* Note using max X for minimum and min X for maximum */
error_number = daft_set_height ( symbol , ( float ) ( ( 4.22 * 39 ) / 25.4 ) , ( float ) ( ( 5.84 * 47 ) / 25.4 ) ) ;
# else
symbol - > row_height [ 0 ] = 4.0f ;
symbol - > row_height [ 1 ] = 2.0f ;
daft_set_height ( symbol , 0.0f , 0.0f ) ;
# endif
2018-02-06 20:57:01 +00:00
symbol - > rows = 3 ;
symbol - > width = j - 1 ;
2021-06-10 11:15:39 +01:00
2021-06-19 13:11:23 +01:00
return error_number ;
2018-02-06 20:57:01 +00:00
}