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