2016-08-24 21:39:39 +03:00
/* codablock.c - Handles Codablock-F and Codablock-E */
/*
libzint - the open source barcode library
2021-06-19 15:11:23 +03:00
Copyright ( C ) 2016 - 2021 Harald Oehlmann
2016-08-24 21:39:39 +03:00
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
2016-09-12 16:49:17 +03:00
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2016-08-24 21:39:39 +03:00
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
2016-09-12 16:49:17 +03:00
documentation and / or other materials provided with the distribution .
2016-08-24 21:39:39 +03: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
2016-09-12 16:49:17 +03:00
without specific prior written permission .
2016-08-24 21:39:39 +03: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
2016-09-12 16:49:17 +03:00
OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
2016-08-24 21:39:39 +03:00
SUCH DAMAGE .
*/
2019-11-27 19:16:14 +03:00
/* vim: set ts=4 sw=4 et : */
2016-08-24 21:39:39 +03:00
# include <stdio.h>
2016-09-04 13:04:41 +03:00
# include <math.h>
2016-08-31 17:29:21 +03:00
# ifdef _MSC_VER
2016-09-12 16:49:17 +03:00
# include <malloc.h>
2016-08-31 17:29:21 +03:00
# endif
2020-05-16 12:22:33 +03:00
# include <assert.h>
2016-08-24 21:39:39 +03:00
# include "common.h"
2021-10-21 01:05:30 +03:00
# include "code128.h"
2016-09-04 13:04:41 +03:00
2016-08-31 17:29:21 +03:00
# define uchar unsigned char
2016-08-24 21:39:39 +03:00
2016-09-12 16:49:17 +03:00
/* FTab C128 flags - may be added */
2016-08-31 17:29:21 +03:00
# define CodeA 1
# define CodeB 2
# define CodeC 4
# define CEnd 8
# define CShift 16
# define CFill 32
# define CodeFNC1 64
2020-05-16 12:22:33 +03:00
# define CodeFNC4 128
2016-09-04 13:04:41 +03:00
# define ZTNum (CodeA+CodeB+CodeC)
# define ZTFNC1 (CodeA+CodeB+CodeC+CodeFNC1)
/* ASCII-Extension for Codablock-F */
# define aFNC1 (uchar)(128)
# define aFNC2 (uchar)(129)
# define aFNC3 (uchar)(130)
# define aFNC4 (uchar)(131)
# define aCodeA (uchar)(132)
# define aCodeB (uchar)(133)
# define aCodeC (uchar)(134)
# define aShift (uchar)(135)
2016-08-31 17:29:21 +03:00
/* Code F Analysing-Chart */
typedef struct sCharacterSetTable
{
2016-09-12 16:49:17 +03:00
int CharacterSet ; /* Still possible character sets for actual*/
int AFollowing ; /* Still following Characters in Charset A */
int BFollowing ; /* Still following Characters in Charset B */
int CFollowing ; /* Still following Characters in Charset C */
2016-08-31 17:29:21 +03:00
} CharacterSetTable ;
2016-09-12 16:49:17 +03:00
/* Find the possible Code-128 Character sets for a character
2020-05-16 12:22:33 +03:00
* The result is an or of CodeA , CodeB , CodeC , CodeFNC1 , CodeFNC4 depending on the
2016-08-31 17:29:21 +03:00
* possible Code 128 character sets .
*/
2019-12-19 03:37:55 +03:00
static int GetPossibleCharacterSet ( unsigned char C )
2016-08-31 17:29:21 +03:00
{
2020-03-25 22:27:34 +03:00
if ( C < = ' \x1f ' ) /* Control chars */
2016-09-12 16:49:17 +03:00
return CodeA ;
if ( C > = ' 0 ' & & C < = ' 9 ' )
return ZTNum ; /* ZTNum=CodeA+CodeB+CodeC */
2021-08-10 14:04:25 +03:00
if ( C = = aFNC1 ) /* FNC1s (GS1) not used */
return ZTFNC1 ; /* ZTFNC1=CodeA+CodeB+CodeC+CodeFNC1 */ /* Not reached */
2020-05-16 12:22:33 +03:00
if ( C = = aFNC4 )
return ( CodeA | CodeB | CodeFNC4 ) ;
2016-09-12 16:49:17 +03:00
if ( C > = ' \x60 ' & & C < = ' \x7f ' ) /* 60 to 127 */
return CodeB ;
return CodeA + CodeB ;
2016-08-31 17:29:21 +03:00
}
/* Create a Table with the following information for each Data character:
2020-05-16 12:22:33 +03:00
* int CharacterSet is an or of CodeA , CodeB , CodeC , CodeFNC1 , CodeFNC4 ,
* depending on which character set is applicable .
2016-09-12 16:49:17 +03:00
* ( Result of GetPossibleCharacterSet )
* int AFollowing , BFollowing The number of source characters you still may encode
* in this character set .
* int CFollowing The number of characters encodable in CodeC if we
* start here .
2016-08-31 17:29:21 +03:00
*/
2020-04-03 21:40:59 +03:00
static void CreateCharacterSetTable ( CharacterSetTable T [ ] , unsigned char * data , const int dataLength )
2016-08-31 17:29:21 +03:00
{
2016-09-12 16:49:17 +03:00
int charCur ;
int runChar ;
/* Treat the Data backwards */
charCur = dataLength - 1 ;
T [ charCur ] . CharacterSet = GetPossibleCharacterSet ( data [ charCur ] ) ;
T [ charCur ] . AFollowing = ( ( T [ charCur ] . CharacterSet & CodeA ) = = 0 ) ? 0 : 1 ;
T [ charCur ] . BFollowing = ( ( T [ charCur ] . CharacterSet & CodeB ) = = 0 ) ? 0 : 1 ;
T [ charCur ] . CFollowing = 0 ;
for ( charCur - - ; charCur > = 0 ; charCur - - )
{
T [ charCur ] . CharacterSet = GetPossibleCharacterSet ( data [ charCur ] ) ;
T [ charCur ] . AFollowing =
( ( T [ charCur ] . CharacterSet & CodeA ) = = 0 ) ? 0 : T [ charCur + 1 ] . AFollowing + 1 ;
T [ charCur ] . BFollowing =
( ( T [ charCur ] . CharacterSet & CodeB ) = = 0 ) ? 0 : T [ charCur + 1 ] . BFollowing + 1 ;
T [ charCur ] . CFollowing = 0 ;
}
/* Find the CodeC-chains */
for ( charCur = 0 ; charCur < dataLength ; charCur + + )
{
T [ charCur ] . CFollowing = 0 ;
if ( ( T [ charCur ] . CharacterSet & CodeC ) ! = 0 )
{
/* CodeC possible */
runChar = charCur ;
do {
2020-04-03 21:40:59 +03:00
/* Whether this is FNC1, whether next is */
2016-09-12 16:49:17 +03:00
/* numeric */
2021-08-10 14:04:25 +03:00
if ( T [ runChar ] . CharacterSet = = ZTFNC1 ) /* FNC1s (GS1) not used */
2016-09-12 16:49:17 +03:00
/* FNC1 */
2021-08-10 14:04:25 +03:00
+ + ( T [ charCur ] . CFollowing ) ; /* Not reached */
2016-09-12 16:49:17 +03:00
else
{
+ + runChar ;
if ( runChar > = dataLength )
break ;
/* Only a Number may follow */
if ( T [ runChar ] . CharacterSet = = ZTNum )
T [ charCur ] . CFollowing + = 2 ;
else
break ;
}
+ + runChar ;
} while ( runChar < dataLength ) ;
}
}
2016-08-31 17:29:21 +03:00
}
2016-09-12 16:49:17 +03:00
/* Find the amount of numerical characters in pairs which will fit in
* one bundle into the line ( up to here ) . This is calculated online because
2016-08-31 17:29:21 +03:00
* it depends on the space in the line .
*/
2019-12-19 03:37:55 +03:00
static int RemainingDigits ( CharacterSetTable * T , int charCur , int emptyColumns )
2016-08-31 17:29:21 +03:00
{
2016-09-12 16:49:17 +03:00
int digitCount ; /* Numerical digits fitting in the line */
int runChar ;
runChar = charCur ;
digitCount = 0 ;
while ( emptyColumns > 0 & & runChar < charCur + T [ charCur ] . CFollowing )
{
if ( T [ runChar ] . CharacterSet ! = ZTFNC1 )
{
/* NOT FNC1 */
digitCount + = 2 ;
runChar + + ;
}
runChar + + ;
emptyColumns - - ;
}
return digitCount ;
2016-08-31 17:29:21 +03:00
}
2016-09-12 16:49:17 +03:00
/* Find the Character distribution at a given column count.
2020-04-03 21:40:59 +03:00
* If too many rows ( > 44 ) are requested the columns are extended .
2016-08-31 17:29:21 +03:00
* Parameters :
2016-09-12 16:49:17 +03:00
* T Pointer on the Characters which fit in the row
* If a different count is calculated it is corrected
* in the callers workspace .
* pFillings Output of filling characters
* pSet Output of the character sets used , allocated by me .
* Return value Resulting row count
2016-08-31 17:29:21 +03:00
*/
2020-04-03 21:40:59 +03:00
static int Columns2Rows ( struct zint_symbol * symbol , CharacterSetTable * T , const int dataLength ,
2016-09-12 16:49:17 +03:00
int * pRows , int * pUseColumns , int * pSet , int * pFillings )
2016-08-31 17:29:21 +03:00
{
2016-09-12 16:49:17 +03:00
int useColumns ; /* Usable Characters per line */
2021-07-06 19:21:42 +03:00
int fillings = 0 ; /* Number of filling characters */
2016-09-12 16:49:17 +03:00
int rowsCur ;
int runChar ;
int emptyColumns ; /* Number of codes still empty in line. */
int emptyColumns2 ; /* Alternative emptyColumns to compare */
int CPaires ; /* Number of digit pairs which may fit in the line */
int characterSetCur ; /* Current Character Set */
2020-05-16 12:22:33 +03:00
int isFNC4 ; /* Set if current character FNC4 */
2016-09-12 16:49:17 +03:00
useColumns = * pUseColumns ;
2020-05-16 12:22:33 +03:00
/* >>> Loop until rowsCur <= 44 */
2016-09-12 16:49:17 +03:00
do {
2017-10-23 22:34:31 +03:00
int charCur = 0 ;
2016-09-12 16:49:17 +03:00
memset ( pSet , 0 , dataLength * sizeof ( int ) ) ;
rowsCur = 0 ;
2020-05-16 12:22:33 +03:00
/* >>> Line Loop */
2016-09-12 16:49:17 +03:00
do {
/* >> Start Character */
emptyColumns = useColumns ; /* Remained place in Line */
/* >>Choose in Set A or B */
/* (C is changed as an option later on) */
pSet [ charCur ] = characterSetCur =
( T [ charCur ] . AFollowing > T [ charCur ] . BFollowing )
? CodeA : CodeB ;
/* >> Test on Numeric Mode C */
CPaires = RemainingDigits ( T , charCur , emptyColumns ) ;
if ( CPaires > = 4 )
{
/* 4 Digits in Numeric compression ->OK */
/* > May an odd start find more ? */
/* Skip leading <FNC1>'s */
/* Typical structure : <FNC1><FNC1>12... */
/* Test if numeric after one isn't better.*/
runChar = charCur ;
emptyColumns2 = emptyColumns ;
2021-08-10 14:04:25 +03:00
while ( T [ runChar ] . CharacterSet = = ZTFNC1 ) /* FNC1s (GS1) not used */
2016-09-12 16:49:17 +03:00
{
2021-08-10 14:04:25 +03:00
+ + runChar ; /* Not reached */
2016-09-12 16:49:17 +03:00
- - emptyColumns2 ;
}
if ( CPaires > = RemainingDigits ( T , runChar + 1 , emptyColumns2 - 1 ) )
{
/* Start odd is not better */
/* We start in C */
pSet [ charCur ] = characterSetCur = CodeC ;
2020-05-16 12:22:33 +03:00
/* Increment charCur */
2016-09-12 16:49:17 +03:00
if ( T [ charCur ] . CharacterSet ! = ZTFNC1 )
+ + charCur ; /* 2 Num.Digits */
}
}
+ + charCur ;
- - emptyColumns ;
/* >> Following characters */
while ( emptyColumns > 0 & & charCur < dataLength )
{
2020-05-16 12:22:33 +03:00
isFNC4 = ( T [ charCur ] . CharacterSet & CodeFNC4 ) ;
2016-09-12 16:49:17 +03:00
switch ( characterSetCur ) {
case CodeA :
case CodeB :
/* >> Check switching to CodeC */
/* Switch if :
* - Character not FNC1
* - 4 real Digits will fit in line
* - an odd Start will not be better
*/
if ( T [ charCur ] . CharacterSet = = ZTNum
& & ( CPaires = RemainingDigits ( T , charCur , emptyColumns - 1 ) ) > = 4
& & CPaires > RemainingDigits ( T , charCur + 1 , emptyColumns - 2 ) )
{
/* > Change to C */
pSet [ charCur ] = characterSetCur = CodeC ;
charCur + = 2 ; /* 2 Digit */
emptyColumns - = 2 ; /* <SwitchC>12 */
} else if ( characterSetCur = = CodeA )
{
2020-05-16 12:22:33 +03:00
if ( T [ charCur ] . AFollowing = = 0 | | ( isFNC4 & & T [ charCur ] . AFollowing = = 1 ) )
2016-09-12 16:49:17 +03:00
{
/* Must change to B */
2020-05-16 12:22:33 +03:00
if ( emptyColumns = = 1 | | ( isFNC4 & & emptyColumns = = 2 ) )
2016-09-12 16:49:17 +03:00
{
/* Can't switch: */
pSet [ charCur - 1 ] | = CEnd + CFill ;
emptyColumns = 0 ;
} else {
/* <Shift> or <switchB>? */
2020-05-16 12:22:33 +03:00
if ( T [ charCur ] . BFollowing = = 1 | | ( isFNC4 & & T [ charCur ] . BFollowing = = 2 ) )
2017-04-03 12:47:39 +03:00
{
2021-06-19 15:11:23 +03:00
/* Note using order "FNC4 shift char" (same as CODE128) not "shift FNC4 char" as
given in Table B .1 and Table B .2 */
2020-05-16 12:22:33 +03:00
if ( isFNC4 ) { /* So skip FNC4 and shift value instead */
- - emptyColumns ;
+ + charCur ;
}
2017-04-03 12:47:39 +03:00
pSet [ charCur ] | = CShift ;
} else {
pSet [ charCur ] | = CodeB ;
characterSetCur = CodeB ;
}
2016-09-12 16:49:17 +03:00
emptyColumns - = 2 ;
+ + charCur ;
}
2020-05-16 12:22:33 +03:00
} else if ( isFNC4 & & emptyColumns = = 1 ) {
/* Can't fit extended ASCII on same line */
pSet [ charCur - 1 ] | = CEnd + CFill ;
emptyColumns = 0 ;
2016-09-12 16:49:17 +03:00
} else {
- - emptyColumns ;
+ + charCur ;
}
} else { /* Last possibility : CodeB */
2020-05-16 12:22:33 +03:00
if ( T [ charCur ] . BFollowing = = 0 | | ( isFNC4 & & T [ charCur ] . BFollowing = = 1 ) )
2016-09-12 16:49:17 +03:00
{
/* Must change to A */
2020-05-16 12:22:33 +03:00
if ( emptyColumns = = 1 | | ( isFNC4 & & emptyColumns = = 2 ) )
2016-09-12 16:49:17 +03:00
{
/* Can't switch: */
pSet [ charCur - 1 ] | = CEnd + CFill ;
emptyColumns = 0 ;
} else {
/* <Shift> or <switchA>? */
2020-05-16 12:22:33 +03:00
if ( T [ charCur ] . AFollowing = = 1 | | ( isFNC4 & & T [ charCur ] . AFollowing = = 2 ) )
2017-04-03 12:47:39 +03:00
{
2021-06-19 15:11:23 +03:00
/* Note using order "FNC4 shift char" (same as CODE128) not "shift FNC4 char" as
given in Table B .1 and Table B .2 */
2020-05-16 12:22:33 +03:00
if ( isFNC4 ) { /* So skip FNC4 and shift value instead */
- - emptyColumns ;
+ + charCur ;
}
2017-04-03 12:47:39 +03:00
pSet [ charCur ] | = CShift ;
} else {
pSet [ charCur ] | = CodeA ;
characterSetCur = CodeA ;
}
2016-09-12 16:49:17 +03:00
emptyColumns - = 2 ;
+ + charCur ;
}
2020-05-16 12:22:33 +03:00
} else if ( isFNC4 & & emptyColumns = = 1 ) {
/* Can't fit extended ASCII on same line */
pSet [ charCur - 1 ] | = CEnd + CFill ;
emptyColumns = 0 ;
2016-09-12 16:49:17 +03:00
} else {
- - emptyColumns ;
+ + charCur ;
}
}
break ;
case CodeC :
if ( T [ charCur ] . CFollowing > 0 )
{
charCur + = ( T [ charCur ] . CharacterSet = = ZTFNC1 ) ? 1 : 2 ;
emptyColumns - - ;
} else {
/* Must change to A or B */
if ( emptyColumns = = 1 )
{
/* Can't switch: */
pSet [ charCur - 1 ] | = CEnd + CFill ;
emptyColumns = 0 ;
} else {
/*<SwitchA> or <switchA>?*/
characterSetCur = pSet [ charCur ] =
( T [ charCur ] . AFollowing > T [ charCur ] . BFollowing )
? CodeA : CodeB ;
emptyColumns - = 2 ;
+ + charCur ;
}
}
break ;
} /* switch */
} /* while */
/* > End of Codeline */
pSet [ charCur - 1 ] | = CEnd ;
+ + rowsCur ;
} while ( charCur < dataLength ) ; /* <= Data.Len-1 */
2020-05-16 12:22:33 +03:00
/* Allow for check characters K1, K2 */
switch ( emptyColumns ) {
case 1 :
pSet [ charCur - 1 ] | = CFill ;
/* fall through */
case 0 :
+ + rowsCur ;
fillings = useColumns - 2 + emptyColumns ;
break ;
case 2 :
2016-09-12 16:49:17 +03:00
fillings = 0 ;
2020-05-16 12:22:33 +03:00
break ;
default :
pSet [ charCur - 1 ] | = CFill ;
fillings = emptyColumns - 2 ;
2016-09-12 16:49:17 +03:00
}
if ( rowsCur > 44 ) {
+ + useColumns ;
if ( useColumns > 62 ) {
return ZINT_ERROR_TOO_LONG ;
}
2020-05-16 12:22:33 +03:00
} else if ( rowsCur = = 1 ) {
rowsCur = 2 ;
fillings + = useColumns ;
2016-09-12 16:49:17 +03:00
}
} while ( rowsCur > 44 ) ;
2020-03-25 22:27:34 +03:00
if ( symbol - > debug & ZINT_DEBUG_PRINT ) {
2016-09-12 16:49:17 +03:00
printf ( " -> out: rowsCur <%i>, useColumns <%i>, fillings <%i> \n " , rowsCur , useColumns , fillings ) ;
2020-03-25 22:27:34 +03:00
}
2016-09-12 16:49:17 +03:00
* pUseColumns = useColumns ;
* pRows = rowsCur ;
* pFillings = fillings ;
return 0 ;
2016-08-31 17:29:21 +03:00
}
2020-05-16 12:22:33 +03:00
2016-09-12 16:49:17 +03:00
/* Find columns if row count is given.
2016-08-31 17:29:21 +03:00
*/
2020-04-03 21:40:59 +03:00
static int Rows2Columns ( struct zint_symbol * symbol , CharacterSetTable * T , const int dataLength ,
2016-09-12 16:49:17 +03:00
int * pRows , int * pUseColumns , int * pSet , int * pFillings )
2016-08-31 17:29:21 +03:00
{
2016-09-12 16:49:17 +03:00
int rowsCur ;
int rowsRequested ; /* Number of requested rows */
2020-05-16 12:22:33 +03:00
int columnsRequested ; /* Number of requested columns (if any) */
2016-09-12 16:49:17 +03:00
int fillings ;
int useColumns ;
int testColumns ; /* To enter into Width2Rows */
int testListSize = 0 ;
2021-08-10 14:04:25 +03:00
int pTestList [ 62 + 1 ] ;
2016-09-04 13:04:41 +03:00
# ifndef _MSC_VER
2016-09-12 16:49:17 +03:00
int * pBackupSet [ dataLength ] ;
2016-09-04 13:04:41 +03:00
# else
2016-09-12 16:49:17 +03:00
int * pBackupSet = ( int * ) _alloca ( dataLength * sizeof ( int ) ) ;
2016-08-31 17:29:21 +03:00
# endif
2016-09-12 16:49:17 +03:00
rowsRequested = * pRows ;
2020-05-16 12:22:33 +03:00
columnsRequested = * pUseColumns > = 4 ? * pUseColumns : 0 ;
2016-09-12 16:49:17 +03:00
2020-03-25 22:27:34 +03:00
if ( symbol - > debug & ZINT_DEBUG_PRINT ) {
2020-05-16 12:22:33 +03:00
printf ( " Optimizer : Searching <%i> rows \n " , rowsRequested ) ;
2020-03-25 22:27:34 +03:00
}
2016-09-12 16:49:17 +03:00
2020-05-16 12:22:33 +03:00
if ( columnsRequested ) {
testColumns = columnsRequested ;
} else {
2016-09-12 16:49:17 +03:00
/* First guess */
testColumns = dataLength / rowsRequested ;
if ( testColumns > 62 )
testColumns = 62 ;
2020-05-16 12:22:33 +03:00
else if ( testColumns < 4 )
testColumns = 4 ;
2016-09-12 16:49:17 +03:00
}
2017-10-23 22:34:31 +03:00
for ( ; ; ) {
2017-10-16 20:26:54 +03:00
int errorCur ;
2016-09-12 16:49:17 +03:00
pTestList [ testListSize ] = testColumns ;
testListSize + + ;
useColumns = testColumns ; /* Make a copy because it may be modified */
2020-04-03 21:40:59 +03:00
errorCur = Columns2Rows ( symbol , T , dataLength , & rowsCur , & useColumns , pSet , & fillings ) ;
2016-09-12 16:49:17 +03:00
if ( errorCur ! = 0 )
return errorCur ;
if ( rowsCur < = rowsRequested ) {
/* Less or exactly line number found */
2020-05-16 12:22:33 +03:00
/* check if column count below already tested or at smallest/requested */
int fInTestList = ( rowsCur = = 2 | | testColumns = = 4 | | testColumns = = columnsRequested ) ;
2016-09-12 16:49:17 +03:00
int posCur ;
for ( posCur = 0 ; posCur < testListSize & & ! fInTestList ; posCur + + ) {
if ( pTestList [ posCur ] = = testColumns - 1 )
fInTestList = 1 ;
}
if ( fInTestList ) {
/* >> Smaller Width already tested
*/
2020-05-16 12:22:33 +03:00
if ( rowsCur < rowsRequested ) {
fillings + = useColumns * ( rowsRequested - rowsCur ) ;
rowsCur = rowsRequested ;
2016-09-12 16:49:17 +03:00
}
2020-05-16 12:22:33 +03:00
/* Exit with actual */
* pFillings = fillings ;
* pRows = rowsCur ;
* pUseColumns = useColumns ;
return 0 ;
2016-09-12 16:49:17 +03:00
}
/* > Test more rows (shorter CDB) */
memcpy ( pBackupSet , pSet , dataLength * sizeof ( int ) ) ;
- - testColumns ;
} else {
2020-05-16 12:22:33 +03:00
/* > Too many rows */
2016-09-12 16:49:17 +03:00
/* > Test less rows (longer code) */
memcpy ( pBackupSet , pSet , dataLength * sizeof ( int ) ) ;
2021-08-10 14:04:25 +03:00
if ( + + testColumns > 62 ) {
return ZINT_ERROR_TOO_LONG ;
}
2016-09-12 16:49:17 +03:00
}
}
2016-08-31 17:29:21 +03:00
}
2016-09-04 13:04:41 +03:00
/* Print a character in character set A
*/
2019-12-19 03:37:55 +03:00
static void A2C128_A ( uchar * * ppOutPos , uchar c )
2016-09-04 13:04:41 +03:00
{
2016-09-12 16:49:17 +03:00
uchar * pOutPos = * ppOutPos ;
switch ( c ) {
case aCodeB : * pOutPos = 100 ; break ;
case aFNC4 : * pOutPos = 101 ; break ;
2021-08-10 14:04:25 +03:00
case aFNC1 : * pOutPos = 102 ; break ; /* FNC1s (GS1) not used */ /* Not reached */
case aFNC2 : * pOutPos = 97 ; break ; /* FNC2s (Message Append) not used */ /* Not reached */
2016-09-12 16:49:17 +03:00
case aFNC3 : * pOutPos = 96 ; break ;
case aCodeC : * pOutPos = 99 ; break ;
case aShift : * pOutPos = 98 ; break ;
default :
/* +++ HaO 13.11.98 c>' ' && c < '\x1F' corrected */
if ( c > = ' ' & & c < = ' _ ' )
* pOutPos = ( uchar ) ( c - ' ' ) ;
else
* pOutPos = ( uchar ) ( c + 64 ) ;
break ;
}
( * ppOutPos ) + + ;
}
2020-05-16 12:22:33 +03:00
2016-09-04 13:04:41 +03:00
/* Output c in Set B
*/
2019-12-19 03:37:55 +03:00
static void A2C128_B ( uchar * * ppOutPos , uchar c )
2016-09-04 13:04:41 +03:00
{
2016-09-12 16:49:17 +03:00
uchar * pOutPos = * ppOutPos ;
switch ( c ) {
2021-08-10 14:04:25 +03:00
case aFNC1 : * pOutPos = 102 ; break ; /* FNC1s (GS1) not used */ /* Not reached */
case aFNC2 : * pOutPos = 97 ; break ; /* FNC2s (Message Append) not used */ /* Not reached */
2016-09-12 16:49:17 +03:00
case aFNC3 : * pOutPos = 96 ; break ;
case aFNC4 : * pOutPos = 100 ; break ;
case aCodeA : * pOutPos = 101 ; break ;
case aCodeC : * pOutPos = 99 ; break ;
case aShift : * pOutPos = 98 ; break ;
default : * pOutPos = ( uchar ) ( c - ' ' ) ; break ;
}
+ + ( * ppOutPos ) ;
2016-09-04 13:04:41 +03:00
}
2020-05-16 12:22:33 +03:00
2016-09-04 13:04:41 +03:00
/* Output c1, c2 in Set C
*/
2019-12-19 03:37:55 +03:00
static void A2C128_C ( uchar * * ppOutPos , uchar c1 , uchar c2 )
2016-09-04 13:04:41 +03:00
{
2016-09-12 16:49:17 +03:00
uchar * pOutPos = * ppOutPos ;
switch ( c1 ) {
2021-08-10 14:04:25 +03:00
case aFNC1 : * pOutPos = 102 ; break ; /* FNC1s (GS1) not used */ /* Not reached */
2016-09-12 16:49:17 +03:00
case aCodeB : * pOutPos = 100 ; break ;
case aCodeA : * pOutPos = 101 ; break ;
default : * pOutPos = ( char ) ( 10 * ( c1 - ' 0 ' ) + ( c2 - ' 0 ' ) ) ; break ;
}
( * ppOutPos ) + + ;
2016-09-04 13:04:41 +03:00
}
2020-05-16 12:22:33 +03:00
2016-09-04 13:04:41 +03:00
/* Output a character in Characterset
*/
2019-12-19 03:37:55 +03:00
static void ASCIIZ128 ( uchar * * ppOutPos , int CharacterSet , uchar c1 , uchar c2 )
2016-09-04 13:04:41 +03:00
{
2016-09-12 16:49:17 +03:00
if ( CharacterSet = = CodeA )
A2C128_A ( ppOutPos , c1 ) ;
else if ( CharacterSet = = CodeB )
A2C128_B ( ppOutPos , c1 ) ;
else
A2C128_C ( ppOutPos , c1 , c2 ) ;
2016-09-04 13:04:41 +03:00
}
2020-05-16 12:22:33 +03:00
/* XLate Tables D.2, D.3 and F.1 of Codablock-F Specification and call output
2016-09-04 13:04:41 +03:00
*/
2019-12-19 03:37:55 +03:00
static void SumASCII ( uchar * * ppOutPos , int Sum , int CharacterSet )
2016-09-04 13:04:41 +03:00
{
2016-09-12 16:49:17 +03:00
switch ( CharacterSet ) {
2020-05-16 12:22:33 +03:00
case CodeA : /* Row # Indicators and Data Check Characters K1/K2 for CodeA and CodeB are the same */
2016-09-12 16:49:17 +03:00
case CodeB :
if ( Sum < = 31 )
A2C128_B ( ppOutPos , ( uchar ) ( Sum + 96 ) ) ;
else if ( Sum < = 47 )
A2C128_B ( ppOutPos , ( uchar ) Sum ) ;
else
A2C128_B ( ppOutPos , ( uchar ) ( Sum + 10 ) ) ;
break ;
case CodeC :
A2C128_C ( ppOutPos
, ( char ) ( Sum / 10 + ' 0 ' ) , ( uchar ) ( Sum % 10 + ' 0 ' ) ) ;
break ;
}
2016-09-04 13:04:41 +03:00
}
2016-09-12 16:49:17 +03:00
/* Main function called by zint framework
*/
Add compliant height, using ZINT_COMPLIANT_HEIGHT flag for back-compatibility
Rename barcode funcs to same as BARCODE_XXX name
library: barcode funcs array for dispatch, used for ZBarcode_ValidID() also
general: change is_sane() comparison to nonzero from ZINT_ERROR_INVALID_OPTION
MAILMARK: fuller error messages
CODABAR: add option to show check character in HRT
zint.h: use 0xNNNN for OR-able defines
GUI: add guard descent height reset button, add Zint version to window title,
static get_zint_version() method, use QStringLiteral (QSL shorthand),
use SIGNAL(toggled()), add errtxt "popup" and status bar, add icons,
add saveAs shortcut, add main menu, context menus and actions, add help,
reset_view() -> reset_colours(), add copy to clipboard as EMF/GIF/PNG/TIF,
lessen triggering of update_preview(), shorten names of getters/setters,
simplify/shorten some update_preview() logic in switch,
CODEONE disable structapp for Version S
qzint.cpp: add on_errored signal, add missing getters, add test
2021-10-09 02:13:39 +03:00
INTERNAL int codablockf ( struct zint_symbol * symbol , unsigned char source [ ] , int length ) {
2020-04-03 21:40:59 +03:00
int charCur , dataLength ;
2020-09-30 14:19:12 +03:00
int error_number ;
2016-09-12 16:49:17 +03:00
int rows , columns , useColumns ;
int fillings ;
int Sum1 , Sum2 ;
uchar * pOutPos ;
int rowCur ;
int characterSetCur ;
int emptyColumns ;
2020-04-03 21:40:59 +03:00
char dest [ 1000 ] ;
int r , c ;
2016-09-04 13:04:41 +03:00
# ifdef _MSC_VER
2016-09-12 16:49:17 +03:00
CharacterSetTable * T ;
unsigned char * data ;
int * pSet ;
uchar * pOutput ;
2016-09-04 13:04:41 +03:00
# endif
2020-05-16 12:22:33 +03:00
/* Suppresses clang-analyzer-core.VLASize warning */
assert ( length > 0 ) ;
2016-09-12 16:49:17 +03:00
/* Parameter check */
2020-05-16 12:22:33 +03:00
/* option1: rows <= 0: automatic, 1..44 */
2016-09-12 16:49:17 +03:00
rows = symbol - > option_1 ;
2020-05-16 12:22:33 +03:00
if ( rows = = 1 ) {
Add compliant height, using ZINT_COMPLIANT_HEIGHT flag for back-compatibility
Rename barcode funcs to same as BARCODE_XXX name
library: barcode funcs array for dispatch, used for ZBarcode_ValidID() also
general: change is_sane() comparison to nonzero from ZINT_ERROR_INVALID_OPTION
MAILMARK: fuller error messages
CODABAR: add option to show check character in HRT
zint.h: use 0xNNNN for OR-able defines
GUI: add guard descent height reset button, add Zint version to window title,
static get_zint_version() method, use QStringLiteral (QSL shorthand),
use SIGNAL(toggled()), add errtxt "popup" and status bar, add icons,
add saveAs shortcut, add main menu, context menus and actions, add help,
reset_view() -> reset_colours(), add copy to clipboard as EMF/GIF/PNG/TIF,
lessen triggering of update_preview(), shorten names of getters/setters,
simplify/shorten some update_preview() logic in switch,
CODEONE disable structapp for Version S
qzint.cpp: add on_errored signal, add missing getters, add test
2021-10-09 02:13:39 +03:00
error_number = code128 ( symbol , source , length ) ; /* Only returns errors, not warnings */
2020-09-30 14:19:12 +03:00
if ( error_number < ZINT_ERROR ) {
2020-05-16 12:22:33 +03:00
symbol - > output_options | = BARCODE_BIND ;
if ( symbol - > border_width = = 0 ) { /* Allow override if non-zero */
2020-05-21 20:22:28 +03:00
symbol - > border_width = 1 ; /* AIM ISS-X-24 Section 4.6.1 b) (note change from previous default 2) */
2020-05-16 12:22:33 +03:00
}
2020-09-30 14:19:12 +03:00
symbol - > text [ 0 ] = ' \0 ' ; /* Disable HRT for compatibility with CODABLOCKF */
Add compliant height, using ZINT_COMPLIANT_HEIGHT flag for back-compatibility
Rename barcode funcs to same as BARCODE_XXX name
library: barcode funcs array for dispatch, used for ZBarcode_ValidID() also
general: change is_sane() comparison to nonzero from ZINT_ERROR_INVALID_OPTION
MAILMARK: fuller error messages
CODABAR: add option to show check character in HRT
zint.h: use 0xNNNN for OR-able defines
GUI: add guard descent height reset button, add Zint version to window title,
static get_zint_version() method, use QStringLiteral (QSL shorthand),
use SIGNAL(toggled()), add errtxt "popup" and status bar, add icons,
add saveAs shortcut, add main menu, context menus and actions, add help,
reset_view() -> reset_colours(), add copy to clipboard as EMF/GIF/PNG/TIF,
lessen triggering of update_preview(), shorten names of getters/setters,
simplify/shorten some update_preview() logic in switch,
CODEONE disable structapp for Version S
qzint.cpp: add on_errored signal, add missing getters, add test
2021-10-09 02:13:39 +03:00
if ( symbol - > output_options & COMPLIANT_HEIGHT ) {
/* AIM ISS-X-24 Section 4.5.1 minimum row height 8 (for compatibility with CODABLOCKF, not specced for
CODE128 ) */
error_number = set_height ( symbol , 8.0f , 10.0f , 0.0f , 0 /*no_errtxt*/ ) ;
} else {
( void ) set_height ( symbol , 0.0f , 5.0f , 0.0f , 1 /*no_errtxt*/ ) ;
}
2020-05-16 12:22:33 +03:00
}
2020-09-30 14:19:12 +03:00
return error_number ;
2020-05-16 12:22:33 +03:00
}
2016-09-12 16:49:17 +03:00
if ( rows > 44 ) {
2020-04-03 21:40:59 +03:00
strcpy ( symbol - > errtxt , " 410: Rows parameter not in 0..44 " ) ;
2016-09-12 16:49:17 +03:00
return ZINT_ERROR_INVALID_OPTION ;
}
2020-05-16 12:22:33 +03:00
/* option_2: (usable data) columns: <= 0: automatic, 9..67 (min 9 == 4 data, max 67 == 62 data) */
2016-09-12 16:49:17 +03:00
columns = symbol - > option_2 ;
2020-05-16 12:22:33 +03:00
if ( ! ( columns < = 0 | | ( columns > = 9 & & columns < = 67 ) ) ) {
strcpy ( symbol - > errtxt , " 411: Columns parameter not in 0, 9..67 " ) ;
2016-09-12 16:49:17 +03:00
return ZINT_ERROR_INVALID_OPTION ;
}
2020-05-16 12:22:33 +03:00
2016-09-04 13:04:41 +03:00
# ifndef _MSC_VER
2016-09-12 16:49:17 +03:00
unsigned char data [ length * 2 + 1 ] ;
2016-09-04 13:04:41 +03:00
# else
2016-09-12 16:49:17 +03:00
data = ( unsigned char * ) _alloca ( length * 2 + 1 ) ;
2016-08-31 17:29:21 +03:00
# endif
2016-09-12 16:49:17 +03:00
dataLength = 0 ;
if ( symbol - > output_options & READER_INIT ) {
data [ dataLength ] = aFNC3 ;
dataLength + + ;
}
/* Replace all Codes>127 with <fnc4>Code-128 */
2020-12-21 22:30:07 +03:00
for ( charCur = 0 ; charCur < length ; charCur + + ) {
2016-09-12 16:49:17 +03:00
if ( source [ charCur ] > 127 )
{
data [ dataLength ] = aFNC4 ;
dataLength + + ;
data [ dataLength ] = ( unsigned char ) ( source [ charCur ] & 127 ) ;
} else
data [ dataLength ] = source [ charCur ] ;
dataLength + + ;
}
/* Build character set table */
2016-09-04 13:04:41 +03:00
# ifndef _MSC_VER
2016-09-12 16:49:17 +03:00
CharacterSetTable T [ dataLength ] ;
int pSet [ dataLength ] ;
2016-09-04 13:04:41 +03:00
# else
2016-09-12 16:49:17 +03:00
T = ( CharacterSetTable * ) _alloca ( dataLength * sizeof ( CharacterSetTable ) ) ;
pSet = ( int * ) _alloca ( dataLength * sizeof ( int ) ) ;
2016-09-04 13:04:41 +03:00
# endif
2016-09-12 16:49:17 +03:00
CreateCharacterSetTable ( T , data , dataLength ) ;
/* Find final row and column count */
/* nor row nor column count given */
2020-05-16 12:22:33 +03:00
if ( rows < = 0 & & columns < = 0 ) {
/* use 1/1 aspect/ratio Codablock */
2020-12-21 22:30:07 +03:00
columns = ( int ) floor ( sqrt ( dataLength ) ) + 5 ;
2020-05-16 12:22:33 +03:00
if ( columns > 67 ) {
columns = 67 ;
} else if ( columns < 9 ) {
columns = 9 ;
}
if ( symbol - > debug & ZINT_DEBUG_PRINT ) {
printf ( " Auto column count for %d characters:%d \n " , dataLength , columns ) ;
2016-09-12 16:49:17 +03:00
}
}
2016-10-27 11:32:12 +03:00
/* There are 5 Codewords for Organisation Start(2),row(1),CheckSum,Stop */
useColumns = columns - 5 ;
2016-09-12 16:49:17 +03:00
if ( rows > 0 ) {
/* row count given */
2020-09-30 14:19:12 +03:00
error_number = Rows2Columns ( symbol , T , dataLength , & rows , & useColumns , pSet , & fillings ) ;
2016-09-12 16:49:17 +03:00
} else {
/* column count given */
2020-09-30 14:19:12 +03:00
error_number = Columns2Rows ( symbol , T , dataLength , & rows , & useColumns , pSet , & fillings ) ;
2016-09-12 16:49:17 +03:00
}
2020-09-30 14:19:12 +03:00
if ( error_number ! = 0 ) {
2020-04-03 21:40:59 +03:00
strcpy ( symbol - > errtxt , " 413: Data string too long " ) ;
2020-09-30 14:19:12 +03:00
return error_number ;
2016-09-12 16:49:17 +03:00
}
2020-05-16 12:22:33 +03:00
/* Suppresses clang-analyzer-core.VLASize warning */
assert ( rows > = 2 & & useColumns > = 4 ) ;
/* Data Check Characters K1 and K2, Annex F */
Sum1 = Sum2 = 0 ;
2020-12-21 22:30:07 +03:00
for ( charCur = 0 ; charCur < length ; charCur + + ) {
2020-05-16 12:22:33 +03:00
Sum1 = ( Sum1 + ( charCur + 1 ) * source [ charCur ] ) % 86 ; /* Mod as we go along to avoid overflow */
Sum2 = ( Sum2 + charCur * source [ charCur ] ) % 86 ;
2016-09-12 16:49:17 +03:00
}
2020-03-25 22:27:34 +03:00
if ( symbol - > debug & ZINT_DEBUG_PRINT ) { /* start a new level of local variables */
2016-09-12 16:49:17 +03:00
int DPos ;
printf ( " \n Data: " ) ;
for ( DPos = 0 ; DPos < dataLength ; DPos + + )
fputc ( data [ DPos ] , stdout ) ;
printf ( " \n Set: " ) ;
for ( DPos = 0 ; DPos < dataLength ; DPos + + ) {
switch ( pSet [ DPos ] & ( CodeA + CodeB + CodeC ) ) {
case CodeA : fputc ( ' A ' , stdout ) ; break ;
case CodeB : fputc ( ' B ' , stdout ) ; break ;
case CodeC : fputc ( ' C ' , stdout ) ; break ;
default : fputc ( ' . ' , stdout ) ; break ;
}
}
printf ( " \n FNC1: " ) ;
for ( DPos = 0 ; DPos < dataLength ; DPos + + )
fputc ( ( pSet [ DPos ] & CodeFNC1 ) = = 0 ? ' . ' : ' X ' , stdout ) ;
printf ( " \n END: " ) ;
for ( DPos = 0 ; DPos < dataLength ; DPos + + )
fputc ( ( pSet [ DPos ] & CEnd ) = = 0 ? ' . ' : ' X ' , stdout ) ;
printf ( " \n Shif: " ) ;
for ( DPos = 0 ; DPos < dataLength ; DPos + + )
fputc ( ( pSet [ DPos ] & CShift ) = = 0 ? ' . ' : ' X ' , stdout ) ;
printf ( " \n FILL: " ) ;
for ( DPos = 0 ; DPos < dataLength ; DPos + + )
fputc ( ( pSet [ DPos ] & CFill ) = = 0 ? ' . ' : ' X ' , stdout ) ;
fputc ( ' \n ' , stdout ) ;
2020-05-16 12:22:33 +03:00
printf ( " K1 %d, K2 %d \n " , Sum1 , Sum2 ) ;
2016-09-12 16:49:17 +03:00
}
columns = useColumns + 5 ;
/* >>> Build C128 code numbers */
/* The C128 column count contains Start (2CW), Row ID, Checksum, Stop */
2016-09-04 13:04:41 +03:00
# ifndef _MSC_VER
2016-09-12 16:49:17 +03:00
uchar pOutput [ columns * rows ] ;
2016-09-04 13:04:41 +03:00
# else
2021-06-19 15:11:23 +03:00
pOutput = ( unsigned char * ) _alloca ( columns * rows ) ;
2016-09-04 13:04:41 +03:00
# endif
2016-09-12 16:49:17 +03:00
pOutPos = pOutput ;
charCur = 0 ;
/* >> Loop over rows */
for ( rowCur = 0 ; rowCur < rows ; rowCur + + ) {
if ( charCur > = dataLength )
{
2020-05-16 12:22:33 +03:00
/* >> Empty line with StartA, aCodeB, row #, and then filler aCodeC aCodeB etc */
2016-09-12 16:49:17 +03:00
* pOutPos = ' \x67 ' ;
pOutPos + + ;
2020-05-16 12:22:33 +03:00
* pOutPos = 100 ; /* aCodeB */
2016-09-12 16:49:17 +03:00
pOutPos + + ;
2020-05-16 12:22:33 +03:00
characterSetCur = CodeB ;
SumASCII ( & pOutPos , rowCur + 42 , characterSetCur ) ; /* Row # */
emptyColumns = useColumns ;
if ( rowCur = = rows - 1 ) {
emptyColumns - = 2 ;
}
2016-09-12 16:49:17 +03:00
while ( emptyColumns > 0 )
{
if ( characterSetCur = = CodeC )
{
A2C128_C ( & pOutPos , aCodeB , ' \0 ' ) ;
characterSetCur = CodeB ;
} else {
A2C128_B ( & pOutPos , aCodeC ) ;
characterSetCur = CodeC ;
}
- - emptyColumns ;
}
} else {
/* >> Normal Line */
/* > Startcode */
switch ( pSet [ charCur ] & ( CodeA + CodeB + CodeC ) ) {
case CodeA :
* pOutPos = ' \x67 ' ;
pOutPos + + ;
2020-05-16 12:22:33 +03:00
* pOutPos = ' \x62 ' ;
pOutPos + + ;
2016-09-12 16:49:17 +03:00
characterSetCur = CodeA ;
break ;
case CodeB :
2020-05-16 12:22:33 +03:00
* pOutPos = ' \x67 ' ;
pOutPos + + ;
* pOutPos = ' \x64 ' ;
pOutPos + + ;
2016-09-12 16:49:17 +03:00
characterSetCur = CodeB ;
break ;
case CodeC :
2016-09-13 09:16:51 +03:00
default :
2020-05-16 12:22:33 +03:00
* pOutPos = ' \x67 ' ;
pOutPos + + ;
* pOutPos = ' \x63 ' ;
pOutPos + + ;
2016-09-12 16:49:17 +03:00
characterSetCur = CodeC ;
break ;
2016-09-04 13:04:41 +03:00
}
2020-05-16 12:22:33 +03:00
/* > Set F1 */
/* In first line : # of rows */
SumASCII ( & pOutPos , rowCur = = 0 ? rows - 2 : rowCur + 42 , characterSetCur ) ;
2016-09-12 16:49:17 +03:00
/* >>> Data */
2016-09-12 23:47:40 +03:00
emptyColumns = useColumns ;
2016-09-12 16:49:17 +03:00
/* >> Character loop */
2020-05-16 12:22:33 +03:00
while ( emptyColumns > 0 & & charCur < dataLength )
2016-09-12 16:49:17 +03:00
{
/* ? Change character set */
2020-05-16 12:22:33 +03:00
if ( emptyColumns < useColumns )
2016-09-12 16:49:17 +03:00
{
if ( ( pSet [ charCur ] & CodeA ) ! = 0 )
{
/* Change to A */
ASCIIZ128 ( & pOutPos , characterSetCur , aCodeA , ' \0 ' ) ;
- - emptyColumns ;
characterSetCur = CodeA ;
} else if ( ( pSet [ charCur ] & CodeB ) ! = 0 )
{
/* Change to B */
ASCIIZ128 ( & pOutPos , characterSetCur , aCodeB , ' \0 ' ) ;
- - emptyColumns ;
characterSetCur = CodeB ;
} else if ( ( pSet [ charCur ] & CodeC ) ! = 0 )
{
/* Change to C */
ASCIIZ128 ( & pOutPos , characterSetCur , aCodeC , ' \0 ' ) ;
- - emptyColumns ;
characterSetCur = CodeC ;
}
}
2017-03-30 16:23:14 +03:00
if ( ( pSet [ charCur ] & CShift ) ! = 0 )
2016-09-12 16:49:17 +03:00
{
2016-09-21 00:19:31 +03:00
/* >> Shift it and put out the shifted character */
2016-09-12 16:49:17 +03:00
ASCIIZ128 ( & pOutPos , characterSetCur , aShift , ' \0 ' ) ;
emptyColumns - = 2 ;
characterSetCur = ( characterSetCur = = CodeB ) ? CodeA : CodeB ;
ASCIIZ128 ( & pOutPos , characterSetCur , data [ charCur ] , ' \0 ' ) ;
characterSetCur = ( characterSetCur = = CodeB ) ? CodeA : CodeB ;
} else {
/* Normal Character */
if ( characterSetCur = = CodeC )
{
2021-08-10 14:04:25 +03:00
if ( data [ charCur ] = = aFNC1 ) /* FNC1s (GS1) not used */
A2C128_C ( & pOutPos , aFNC1 , ' \0 ' ) ; /* Not reached */
2016-09-12 16:49:17 +03:00
else
{
2020-12-21 22:30:07 +03:00
A2C128_C ( & pOutPos , data [ charCur ] ,
( uchar ) ( charCur + 1 < dataLength ? data [ charCur + 1 ] : 0 ) ) ;
2016-09-12 16:49:17 +03:00
+ + charCur ;
/* We need this here to get the good index */
/* for the termination flags in Set. */
}
} else
ASCIIZ128 ( & pOutPos , characterSetCur , data [ charCur ] , ' \0 ' ) ;
- - emptyColumns ;
}
/* >> End Criteria */
2020-05-16 12:22:33 +03:00
if ( ( pSet [ charCur ] & CFill ) | | ( pSet [ charCur ] & CEnd ) )
2016-09-12 16:49:17 +03:00
{
/* Fill Line but leave space for checks in last line */
2020-05-16 12:22:33 +03:00
if ( rowCur = = rows - 1 ) {
emptyColumns - = 2 ;
}
2016-09-12 16:49:17 +03:00
while ( emptyColumns > 0 )
{
switch ( characterSetCur ) {
case CodeC :
A2C128_C ( & pOutPos , aCodeB , ' \0 ' ) ;
characterSetCur = CodeB ;
break ;
case CodeB :
A2C128_B ( & pOutPos , aCodeC ) ;
characterSetCur = CodeC ;
break ;
case CodeA :
A2C128_A ( & pOutPos , aCodeC ) ;
characterSetCur = CodeC ;
break ;
}
- - emptyColumns ;
}
}
+ + charCur ;
} /* Loop over characters */
} /* if filling-Line / normal */
/* Add checksum in last line */
2020-05-16 12:22:33 +03:00
if ( rowCur = = rows - 1 )
2016-09-12 16:49:17 +03:00
{
SumASCII ( & pOutPos , Sum1 , characterSetCur ) ;
SumASCII ( & pOutPos , Sum2 , characterSetCur ) ;
}
/* Add Code 128 checksum */
{
2020-05-16 12:22:33 +03:00
int Sum = pOutput [ columns * rowCur ] % 103 ;
int Pos = 1 ;
2016-09-12 16:49:17 +03:00
for ( ; Pos < useColumns + 3 ; Pos + + )
{
2020-05-16 12:22:33 +03:00
Sum = ( Sum + pOutput [ columns * rowCur + Pos ] * Pos ) % 103 ;
2016-09-12 16:49:17 +03:00
}
* pOutPos = ( uchar ) Sum ;
pOutPos + + ;
}
/* Add end character */
* pOutPos = 106 ;
pOutPos + + ;
} /* End Lineloop */
2020-03-25 22:27:34 +03:00
if ( symbol - > debug & ZINT_DEBUG_PRINT ) {
2016-09-12 16:49:17 +03:00
/* Dump the output to the screen
*/
printf ( " \n Code 128 Code Numbers: \n " ) ;
{ /* start a new level of local variables */
int DPos , DPos2 ;
for ( DPos = 0 ; DPos < rows ; DPos + + )
{
for ( DPos2 = 0 ; DPos2 < columns ; DPos2 + + )
{
2016-09-21 00:19:31 +03:00
printf ( " %3d " , ( int ) ( pOutput [ DPos * columns + DPos2 ] ) ) ;
2016-09-12 16:49:17 +03:00
}
printf ( " \n " ) ;
}
}
printf ( " rows=%i columns=%i fillings=%i \n " , rows , columns , fillings ) ;
2020-03-25 22:27:34 +03:00
}
2020-05-16 12:22:33 +03:00
# ifdef ZINT_TEST
if ( symbol - > debug & ZINT_DEBUG_TEST ) {
debug_test_codeword_dump ( symbol , pOutput , rows * columns ) ;
}
# endif
2016-09-12 16:49:17 +03:00
/* Paint the C128 patterns */
for ( r = 0 ; r < rows ; r + + ) {
2021-10-21 01:05:30 +03:00
const int rc = r * columns ;
char * d = dest ;
for ( c = 0 ; c < columns - 1 ; c + + , d + = 6 ) {
memcpy ( d , C128Table [ pOutput [ rc + c ] ] , 6 ) ;
2016-09-04 13:04:41 +03:00
}
2021-10-21 01:05:30 +03:00
memcpy ( d , " 2331112 " , 7 ) ; /* Stop character (106, not in C128Table) */
d + = 7 ;
expand ( symbol , dest , d - dest ) ;
2016-09-12 16:49:17 +03:00
}
2017-10-23 22:37:52 +03:00
Add compliant height, using ZINT_COMPLIANT_HEIGHT flag for back-compatibility
Rename barcode funcs to same as BARCODE_XXX name
library: barcode funcs array for dispatch, used for ZBarcode_ValidID() also
general: change is_sane() comparison to nonzero from ZINT_ERROR_INVALID_OPTION
MAILMARK: fuller error messages
CODABAR: add option to show check character in HRT
zint.h: use 0xNNNN for OR-able defines
GUI: add guard descent height reset button, add Zint version to window title,
static get_zint_version() method, use QStringLiteral (QSL shorthand),
use SIGNAL(toggled()), add errtxt "popup" and status bar, add icons,
add saveAs shortcut, add main menu, context menus and actions, add help,
reset_view() -> reset_colours(), add copy to clipboard as EMF/GIF/PNG/TIF,
lessen triggering of update_preview(), shorten names of getters/setters,
simplify/shorten some update_preview() logic in switch,
CODEONE disable structapp for Version S
qzint.cpp: add on_errored signal, add missing getters, add test
2021-10-09 02:13:39 +03:00
if ( symbol - > output_options & COMPLIANT_HEIGHT ) {
/* AIM ISS-X-24 Section 4.6.1 minimum row height; use 10 * rows as default */
float min_row_height = stripf ( 0.55f * useColumns + 3.0f ) ;
if ( min_row_height < 8.0f ) {
min_row_height = 8.0f ;
}
error_number = set_height ( symbol , min_row_height , ( min_row_height > 10.0f ? min_row_height : 10.0f ) * rows ,
0.0f , 0 /*no_errtxt*/ ) ;
} else {
( void ) set_height ( symbol , 0.0f , 10.0f * rows , 0.0f , 1 /*no_errtxt*/ ) ;
2021-06-19 15:11:23 +03:00
}
2020-05-16 12:22:33 +03:00
symbol - > output_options | = BARCODE_BIND ;
2017-10-23 22:37:52 +03:00
2020-05-16 12:22:33 +03:00
if ( symbol - > border_width = = 0 ) { /* Allow override if non-zero */
2020-05-21 20:22:28 +03:00
symbol - > border_width = 1 ; /* AIM ISS-X-24 Section 4.6.1 b) (note change from previous default 2) */
2016-09-12 23:47:40 +03:00
}
2020-05-21 20:22:28 +03:00
2020-09-30 14:19:12 +03:00
return error_number ;
2016-09-04 13:04:41 +03:00
}