From 8dcd09406c1a50173c83967429576c815e3d7443 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 16 May 2020 10:22:33 +0100 Subject: [PATCH] CODABLOCKF and CODE128 fixes; row separator height option_3; #191 --- backend/codablock.c | 328 ++++++++++++------------ backend/code128.c | 248 +++++++++--------- backend/common.c | 4 +- backend/library.c | 6 +- backend/raster.c | 12 +- backend/tests/test_codablock.c | 399 ++++++++++++++++++++++++----- backend/tests/test_code128.c | 354 +++++++++++++++++++++++--- backend/tests/test_gs1.c | 20 +- backend/tests/test_library.c | 55 ++++ backend/tests/test_raster.c | 81 +++++- backend/tests/test_vector.c | 95 ++++++- backend/tests/testcommon.c | 34 ++- backend/tests/testcommon.h | 1 + backend/vector.c | 15 +- backend_qt/qzint.cpp | 7 +- docs/manual.txt | 19 +- frontend/main.c | 94 +++++-- frontend_qt/grpCodablockF.ui | 446 ++++++++++++++++++++++++++++++--- frontend_qt/mainwindow.cpp | 36 ++- 19 files changed, 1743 insertions(+), 511 deletions(-) diff --git a/backend/codablock.c b/backend/codablock.c index cdaa6073..09646b99 100644 --- a/backend/codablock.c +++ b/backend/codablock.c @@ -37,8 +37,10 @@ #ifdef _MSC_VER #include #endif +#include #include "common.h" -#include "gs1.h" + +INTERNAL int code_128(struct zint_symbol *symbol, const unsigned char source[], const size_t length); #define uchar unsigned char @@ -50,6 +52,7 @@ #define CShift 16 #define CFill 32 #define CodeFNC1 64 +#define CodeFNC4 128 #define ZTNum (CodeA+CodeB+CodeC) #define ZTFNC1 (CodeA+CodeB+CodeC+CodeFNC1) @@ -90,7 +93,7 @@ typedef struct sCharacterSetTable } CharacterSetTable; /* Find the possible Code-128 Character sets for a character - * The result is an or of CodeA,CodeB,CodeC,CodeFNC1 in dependency of the + * The result is an or of CodeA, CodeB, CodeC, CodeFNC1, CodeFNC4 depending on the * possible Code 128 character sets. */ static int GetPossibleCharacterSet(unsigned char C) @@ -101,14 +104,16 @@ static int GetPossibleCharacterSet(unsigned char C) return ZTNum; /* ZTNum=CodeA+CodeB+CodeC */ if (C==aFNC1) return ZTFNC1; /* ZTFNC1=CodeA+CodeB+CodeC+CodeFNC1 */ + if (C==aFNC4) + return (CodeA | CodeB | CodeFNC4); if (C>='\x60' && C<='\x7f') /* 60 to 127 */ return CodeB; return CodeA+CodeB; } /* Create a Table with the following information for each Data character: - * int CharacterSet is an or of CodeA,CodeB,CodeC,CodeFNC1, in - * dependency which character set is applicable. + * int CharacterSet is an or of CodeA, CodeB, CodeC, CodeFNC1, CodeFNC4, + * depending on which character set is applicable. * (Result of GetPossibleCharacterSet) * int AFollowing,BFollowing The number of source characters you still may encode * in this character set. @@ -194,7 +199,6 @@ static int RemainingDigits(CharacterSetTable *T, int charCur,int emptyColumns) /* Find the Character distribution at a given column count. * If too many rows (>44) are requested the columns are extended. - * A one-liner may be choosen if shorter. * Parameters : * T Pointer on the Characters which fit in the row * If a different count is calculated it is corrected @@ -215,24 +219,20 @@ static int Columns2Rows(struct zint_symbol *symbol, CharacterSetTable *T, const int emptyColumns2; /* Alternative emptyColumns to compare */ int CPaires; /* Number of digit pairs which may fit in the line */ int characterSetCur; /* Current Character Set */ + int isFNC4; /* Set if current character FNC4 */ useColumns=*pUseColumns; - if (useColumns<3) - useColumns=3; - /* >>> Loop until rowsCur<44 */ + /* >>> Loop until rowsCur <= 44 */ do { int charCur=0; - int fOneLiner=1; /* First try one-Liner */ memset(pSet,0,dataLength*sizeof(int)); rowsCur=0; - /* >>> Line and OneLiner-try Loop */ + /* >>> Line Loop */ do{ /* >> Start Character */ emptyColumns=useColumns; /* Remained place in Line */ - if (fOneLiner) - emptyColumns+=2; /* >>Choose in Set A or B */ /* (C is changed as an option later on) */ @@ -262,7 +262,7 @@ static int Columns2Rows(struct zint_symbol *symbol, CharacterSetTable *T, const /* Start odd is not better */ /* We start in C */ pSet[charCur]=characterSetCur=CodeC; - /* Inkrement charCur */ + /* Increment charCur */ if (T[charCur].CharacterSet!=ZTFNC1) ++charCur; /* 2 Num.Digits */ } @@ -273,6 +273,7 @@ static int Columns2Rows(struct zint_symbol *symbol, CharacterSetTable *T, const /* >> Following characters */ while(emptyColumns>0 && charCur12 */ } else if (characterSetCur==CodeA) { - if(T[charCur].AFollowing==0) + if (T[charCur].AFollowing == 0 || (isFNC4 && T[charCur].AFollowing == 1)) { /* Must change to B */ - if (emptyColumns==1) + if (emptyColumns == 1 || (isFNC4 && emptyColumns == 2)) { /* Can't switch: */ pSet[charCur-1]|=CEnd+CFill; emptyColumns=0; }else{ /* or ? */ - if (T[charCur].BFollowing==1) + if (T[charCur].BFollowing == 1 || (isFNC4 && T[charCur].BFollowing == 2)) { + /* Note using order "FNC4 shift char" (same as CODE128) not "shift FNC4 char" as given in Table B.1 and Table B.2 */ + if (isFNC4) { /* So skip FNC4 and shift value instead */ + --emptyColumns; + ++charCur; + } pSet[charCur]|=CShift; } else { pSet[charCur]|=CodeB; @@ -312,23 +318,32 @@ static int Columns2Rows(struct zint_symbol *symbol, CharacterSetTable *T, const emptyColumns-=2; ++charCur; } + } else if (isFNC4 && emptyColumns == 1) { + /* Can't fit extended ASCII on same line */ + pSet[charCur-1]|=CEnd+CFill; + emptyColumns=0; }else{ --emptyColumns; ++charCur; } } else { /* Last possibility : CodeB */ - if(T[charCur].BFollowing==0) + if (T[charCur].BFollowing == 0 || (isFNC4 && T[charCur].BFollowing == 1)) { /* Must change to A */ - if (emptyColumns==1) + if (emptyColumns == 1 || (isFNC4 && emptyColumns == 2)) { /* Can't switch: */ pSet[charCur-1]|=CEnd+CFill; emptyColumns=0; } else { /* or ? */ - if (T[charCur].AFollowing==1) + if (T[charCur].AFollowing == 1 || (isFNC4 && T[charCur].AFollowing == 2)) { + /* Note using order "FNC4 shift char" (same as CODE128) not "shift FNC4 char" as given in Table B.1 and Table B.2 */ + if (isFNC4) { /* So skip FNC4 and shift value instead */ + --emptyColumns; + ++charCur; + } pSet[charCur]|=CShift; } else { pSet[charCur]|=CodeA; @@ -337,6 +352,10 @@ static int Columns2Rows(struct zint_symbol *symbol, CharacterSetTable *T, const emptyColumns-=2; ++charCur; } + } else if (isFNC4 && emptyColumns == 1) { + /* Can't fit extended ASCII on same line */ + pSet[charCur-1]|=CEnd+CFill; + emptyColumns=0; }else{ --emptyColumns; ++charCur; @@ -371,43 +390,23 @@ static int Columns2Rows(struct zint_symbol *symbol, CharacterSetTable *T, const /* > End of Codeline */ pSet[charCur-1]|=CEnd; ++rowsCur; - if ( fOneLiner) - { - if (charCur44) { @@ -415,6 +414,9 @@ static int Columns2Rows(struct zint_symbol *symbol, CharacterSetTable *T, const if (useColumns > 62) { return ZINT_ERROR_TOO_LONG; } + } else if (rowsCur == 1) { + rowsCur = 2; + fillings += useColumns; } } while(rowsCur>44); if (symbol->debug & ZINT_DEBUG_PRINT) { @@ -425,6 +427,7 @@ static int Columns2Rows(struct zint_symbol *symbol, CharacterSetTable *T, const *pFillings=fillings; return 0; } + /* Find columns if row count is given. */ static int Rows2Columns(struct zint_symbol *symbol, CharacterSetTable *T, const int dataLength, @@ -432,6 +435,7 @@ static int Rows2Columns(struct zint_symbol *symbol, CharacterSetTable *T, const { int rowsCur; int rowsRequested; /* Number of requested rows */ + int columnsRequested; /* Number of requested columns (if any) */ int backupRows = 0; int fillings; int backupFillings = 0; @@ -448,21 +452,21 @@ static int Rows2Columns(struct zint_symbol *symbol, CharacterSetTable *T, const #endif rowsRequested=*pRows; + columnsRequested = *pUseColumns >= 4 ? *pUseColumns : 0; if (symbol->debug & ZINT_DEBUG_PRINT) { - fprintf(stderr,"Optimizer : Searching <%i> rows\n",rowsRequested); + printf("Optimizer : Searching <%i> rows\n", rowsRequested); } - if (rowsRequested==1) - /* OneLiners are self-calibrating */ - testColumns=32767; - else { + if (columnsRequested) { + testColumns = columnsRequested; + } else { /* First guess */ testColumns=dataLength/rowsRequested; if (testColumns > 62) testColumns = 62; - else if (testColumns < 1) - testColumns = 1; + else if (testColumns < 4) + testColumns = 4; } for (;;) { @@ -475,8 +479,8 @@ static int Rows2Columns(struct zint_symbol *symbol, CharacterSetTable *T, const return errorCur; if (rowsCur<=rowsRequested) { /* Less or exactly line number found */ - /* check if column count below already tested or Count = 1*/ - int fInTestList = (rowsCur == 1 || testColumns == 1); + /* check if column count below already tested or at smallest/requested */ + int fInTestList = (rowsCur == 2 || testColumns == 4 || testColumns == columnsRequested); int posCur; for (posCur = 0; posCur < testListSize && ! fInTestList; posCur++) { if ( pTestList[posCur] == testColumns-1 ) @@ -484,21 +488,16 @@ static int Rows2Columns(struct zint_symbol *symbol, CharacterSetTable *T, const } if (fInTestList) { /* >> Smaller Width already tested - * if rowsCur=rowsRequested->Exit - * if rowsCur0 - * -> New search for rowsRequested:=rowsCur */ - if ( rowsCur == rowsRequested || fillings == 0 || testColumns == 1 ) { - /* Exit with actual */ - *pFillings=fillings; - *pRows=rowsCur; - *pUseColumns = useColumns; - return 0; + if (rowsCur < rowsRequested) { + fillings += useColumns * (rowsRequested - rowsCur); + rowsCur = rowsRequested; } - /* Search again for smaller Line number */ - rowsRequested=rowsCur; - pTestList[0] = testColumns; - testListSize = 1; + /* Exit with actual */ + *pFillings=fillings; + *pRows=rowsCur; + *pUseColumns = useColumns; + return 0; } /* > Test more rows (shorter CDB) */ fBackupOk=(rowsCur==rowsRequested); @@ -508,7 +507,7 @@ static int Rows2Columns(struct zint_symbol *symbol, CharacterSetTable *T, const backupRows=rowsCur; --testColumns; } else { - /* > To many rows */ + /* > Too many rows */ int fInTestList = fBackupOk; int posCur; for (posCur = 0; posCur < testListSize && ! fInTestList; posCur++) { @@ -560,6 +559,7 @@ static void A2C128_A(uchar **ppOutPos,uchar c) } (*ppOutPos)++; } + /* Output c in Set B */ static void A2C128_B(uchar **ppOutPos,uchar c) @@ -577,6 +577,7 @@ static void A2C128_B(uchar **ppOutPos,uchar c) } ++(*ppOutPos); } + /* Output c1, c2 in Set C */ static void A2C128_C(uchar **ppOutPos,uchar c1,uchar c2) @@ -590,6 +591,7 @@ static void A2C128_C(uchar **ppOutPos,uchar c1,uchar c2) } (*ppOutPos)++; } + /* Output a character in Characterset */ static void ASCIIZ128(uchar **ppOutPos, int CharacterSet,uchar c1, uchar c2) @@ -601,14 +603,13 @@ static void ASCIIZ128(uchar **ppOutPos, int CharacterSet,uchar c1, uchar c2) else A2C128_C(ppOutPos,c1,c2); } -/* XLate Table A of Codablock-F Specification and call output + +/* XLate Tables D.2, D.3 and F.1 of Codablock-F Specification and call output */ static void SumASCII(uchar **ppOutPos, int Sum, int CharacterSet) { switch (CharacterSet){ - case CodeA: - A2C128_A(ppOutPos, (uchar)Sum); - break; + case CodeA: /* Row # Indicators and Data Check Characters K1/K2 for CodeA and CodeB are the same */ case CodeB: if (Sum<=31) A2C128_B(ppOutPos, (uchar)(Sum+96)); @@ -644,25 +645,33 @@ INTERNAL int codablock(struct zint_symbol *symbol,const unsigned char source[], int *pSet; uchar * pOutput; #endif + /* Suppresses clang-analyzer-core.VLASize warning */ + assert(length > 0); /* Parameter check */ - /* option1: rows 0: automatic, 1..44 */ + /* option1: rows <= 0: automatic, 1..44 */ rows = symbol->option_1; + if (rows == 1) { + Error = code_128(symbol, source, length); + if (Error < 5) { + symbol->output_options |= BARCODE_BIND; + if (symbol->border_width == 0) { /* Allow override if non-zero */ + symbol->border_width = 2; + } + } + return Error; + } if (rows > 44) { strcpy(symbol->errtxt, "410: Rows parameter not in 0..44"); return ZINT_ERROR_INVALID_OPTION; } - /* option_2: (usable data) columns: 0: automatic, 6..66 */ + /* option_2: (usable data) columns: <= 0: automatic, 9..67 (min 9 == 4 data, max 67 == 62 data) */ columns = symbol->option_2; - if ( ! (columns <= 0 || (columns >= 6 && columns <=66)) ) { - strcpy(symbol->errtxt, "411: Columns parameter not in 0,6..66"); - return ZINT_ERROR_INVALID_OPTION; - } - /* GS1 not implemented */ - if ((symbol->input_mode & 0x07) == GS1_MODE) { - strcpy(symbol->errtxt, "412: GS1 mode not supported"); + if ( ! (columns <= 0 || (columns >= 9 && columns <= 67)) ) { + strcpy(symbol->errtxt, "411: Columns parameter not in 0, 9..67"); return ZINT_ERROR_INVALID_OPTION; } + #ifndef _MSC_VER unsigned char data[length*2+1]; #else @@ -698,19 +707,16 @@ INTERNAL int codablock(struct zint_symbol *symbol,const unsigned char source[], /* Find final row and column count */ /* nor row nor column count given */ - if ( rows <= 0 && columns <= 5 ) { - /* Use Code128 until reasonable size */ - if (dataLength < 9) { - rows = 1; - } else { - /* use 1/1 aspect/ratio Codablock */ - columns = ((int)floor(sqrt(1.0*dataLength))+5); - if (columns > 64) { - columns = 64; - } - if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("Auto column count for %d characters:%d\n", dataLength, columns); - } + if (rows <= 0 && columns <= 0) { + /* use 1/1 aspect/ratio Codablock */ + columns = floor(sqrt(dataLength)) + 5; + 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); } } /* There are 5 Codewords for Organisation Start(2),row(1),CheckSum,Stop */ @@ -726,15 +732,14 @@ INTERNAL int codablock(struct zint_symbol *symbol,const unsigned char source[], strcpy(symbol->errtxt, "413: Data string too long"); return Error; } - /* Checksum */ - Sum1=Sum2=0; - if (rows>1) - { - int charCur; - for (charCur=0 ; charCur= 2 && useColumns >= 4); + + /* Data Check Characters K1 and K2, Annex F */ + Sum1 = Sum2 = 0; + for (charCur = 0; charCur < (int) length; charCur++) { + Sum1 = (Sum1 + (charCur + 1) * source[charCur]) % 86; /* Mod as we go along to avoid overflow */ + Sum2 = (Sum2 + charCur * source[charCur]) % 86; } if (symbol->debug & ZINT_DEBUG_PRINT) { /* start a new level of local variables */ @@ -764,6 +769,7 @@ INTERNAL int codablock(struct zint_symbol *symbol,const unsigned char source[], for (DPos=0 ; DPos< dataLength ; DPos++) fputc((pSet[DPos]&CFill)==0?'.':'X',stdout); fputc('\n',stdout); + printf("K1 %d, K2 %d\n", Sum1, Sum2); } columns = useColumns + 5; @@ -781,15 +787,17 @@ INTERNAL int codablock(struct zint_symbol *symbol,const unsigned char source[], for (rowCur=0 ; rowCur=dataLength) { - /* >> Empty line with StartCCodeBCodeC */ - characterSetCur=CodeC; - /* CDB Start C*/ + /* >> Empty line with StartA, aCodeB, row #, and then filler aCodeC aCodeB etc */ *pOutPos='\x67'; pOutPos++; - *pOutPos='\x63'; + *pOutPos = 100; /* aCodeB */ pOutPos++; - SumASCII(&pOutPos,rowCur+42,CodeC); - emptyColumns=useColumns-2; + characterSetCur = CodeB; + SumASCII(&pOutPos, rowCur + 42, characterSetCur); /* Row # */ + emptyColumns = useColumns; + if (rowCur == rows - 1) { + emptyColumns -= 2; + } while (emptyColumns>0) { if(characterSetCur==CodeC) @@ -809,60 +817,36 @@ INTERNAL int codablock(struct zint_symbol *symbol,const unsigned char source[], case CodeA: *pOutPos = '\x67'; pOutPos++; - if (rows>1) { - *pOutPos = '\x62'; - pOutPos++; - } + *pOutPos = '\x62'; + pOutPos++; characterSetCur=CodeA; break; case CodeB: - if (rows==1) { - *pOutPos = '\x68'; - pOutPos++; - } else { - *pOutPos = '\x67'; - pOutPos++; - *pOutPos = '\x64'; - pOutPos++; - } + *pOutPos = '\x67'; + pOutPos++; + *pOutPos = '\x64'; + pOutPos++; characterSetCur=CodeB; break; case CodeC: default: - if (rows==1) { - *pOutPos = '\x69'; - pOutPos++; - } else { - *pOutPos = '\x67'; - pOutPos++; - *pOutPos = '\x63'; - pOutPos++; - } + *pOutPos = '\x67'; + pOutPos++; + *pOutPos = '\x63'; + pOutPos++; characterSetCur=CodeC; break; } - if (rows>1) - { - /* > Set F1 */ - /* In first line : # of rows */ - /* In Case of CodeA we shifted to CodeB */ - SumASCII(&pOutPos - ,(rowCur==0)?rows-2:rowCur+42 - ,(characterSetCur==CodeA)?CodeB:characterSetCur - ); - } + /* > Set F1 */ + /* In first line : # of rows */ + SumASCII(&pOutPos, rowCur == 0 ? rows - 2 : rowCur + 42, characterSetCur); /* >>> Data */ emptyColumns=useColumns; - /* +++ One liner don't have start/stop code */ - if (rows == 1) - emptyColumns +=2; /* >> Character loop */ - while (emptyColumns>0) + while (emptyColumns > 0 && charCur < dataLength) { /* ? Change character set */ - /* not at first position (It was then the start set) */ - /* +++ special case for one-liner */ - if (emptyColumns> End Criteria */ - if ((pSet[charCur] & CFill)!=0) + if ((pSet[charCur] & CFill) || (pSet[charCur] & CEnd)) { /* Fill Line but leave space for checks in last line */ - if(rowCur==rows-1 && emptyColumns>=2) - emptyColumns-=2; + if (rowCur == rows - 1) { + emptyColumns -= 2; + } while(emptyColumns>0) { switch(characterSetCur){ @@ -934,27 +919,23 @@ INTERNAL int codablock(struct zint_symbol *symbol,const unsigned char source[], --emptyColumns; } } - if ((pSet[charCur] & CEnd)!=0) - emptyColumns=0; ++charCur; } /* Loop over characters */ } /* if filling-Line / normal */ /* Add checksum in last line */ - if(rows>1 && rowCur==rows-1) + if (rowCur == rows - 1) { SumASCII(&pOutPos,Sum1,characterSetCur); SumASCII(&pOutPos,Sum2,characterSetCur); } /* Add Code 128 checksum */ { - int Sum=0; - int Pos=0; + int Sum = pOutput[columns * rowCur] % 103; + int Pos = 1; for ( ; Pos < useColumns+3 ; Pos++) { - Sum = (Sum + - ((Pos==0?1:Pos) * pOutput[columns*rowCur+Pos]) % 103 - ) % 103; + Sum = (Sum + pOutput[columns * rowCur + Pos] * Pos) % 103; } *pOutPos=(uchar)Sum; pOutPos++; @@ -981,6 +962,11 @@ INTERNAL int codablock(struct zint_symbol *symbol,const unsigned char source[], } printf("rows=%i columns=%i fillings=%i\n", rows, columns, fillings); } +#ifdef ZINT_TEST + if (symbol->debug & ZINT_DEBUG_TEST) { + debug_test_codeword_dump(symbol, pOutput, rows * columns); + } +#endif /* Paint the C128 patterns */ for (r = 0; r < rows; r++) { @@ -992,11 +978,9 @@ INTERNAL int codablock(struct zint_symbol *symbol,const unsigned char source[], symbol->row_height[r] = 10; } - if (!(symbol->output_options & BARCODE_BIND)) { - symbol->output_options += BARCODE_BIND; - } + symbol->output_options |= BARCODE_BIND; - if (symbol->border_width < 2) { + if (symbol->border_width == 0) { /* Allow override if non-zero */ symbol->border_width = 2; } return 0; diff --git a/backend/code128.c b/backend/code128.c index 96424e92..a9ee19c1 100644 --- a/backend/code128.c +++ b/backend/code128.c @@ -40,8 +40,6 @@ #include "common.h" #include "gs1.h" -#define TRUE 1 -#define FALSE 0 #define SHIFTA 90 #define LATCHA 91 #define SHIFTB 92 @@ -75,7 +73,6 @@ static const char *C128Table[107] = { /* Determine appropriate mode for a given character */ INTERNAL int parunmodd(const unsigned char llyth) { int modd; - modd = 0; if (llyth <= 31) { modd = SHIFTA; @@ -111,7 +108,7 @@ static void grwp(int *indexliste) { list[0][i - 1] = list[0][i - 1] + list[0][i]; j = i + 1; - /* decreace the list */ + /* decrease the list */ while (j < *(indexliste)) { list[0][j - 1] = list[0][j]; list[1][j - 1] = list[1][j]; @@ -132,7 +129,7 @@ static void dxsmooth(int *indexliste) { int i, last, next; for (i = 0; i < *(indexliste); i++) { - int current = list[1][i]; + int current = list[1][i]; /* Either ABORC, AORB, SHIFTA or SHIFTB */ int length = list[0][i]; if (i != 0) { last = list[1][i - 1]; @@ -146,97 +143,82 @@ static void dxsmooth(int *indexliste) { } if (i == 0) { /* first block */ - if ((*(indexliste) == 1) && ((length == 2) && (current == ABORC))) { - /* Rule 1a */ - list[1][i] = LATCHC; - } if (current == ABORC) { - if (length >= 4) { + if ((*(indexliste) == 1) && (length == 2)) { + /* Rule 1a */ + list[1][i] = LATCHC; + current = LATCHC; + } else if (length >= 4) { /* Rule 1b */ list[1][i] = LATCHC; + current = LATCHC; } else { - list[1][i] = AORB; - current = AORB; + current = AORB; /* Determine below */ } } - 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) { + if (next == SHIFTA) { + /* Rule 1c */ + list[1][i] = LATCHA; + } else { + /* Rule 1d */ + list[1][i] = LATCHB; + } + } else if (current == SHIFTA) { + /* Rule 1c */ + list[1][i] = LATCHA; + } else if (current == SHIFTB) { /* Unless LATCHC set above, can only be SHIFTB */ /* 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 (length >= 4) { + /* Rule 3 */ + list[1][i] = LATCHC; + current = LATCHC; + } else { + current = AORB; /* Determine below */ + } } if (current == AORB) { - list[1][i] = LATCHB; - current = LATCHB; + if (last == LATCHA || last == SHIFTB) { /* Maintain state */ + list[1][i] = LATCHA; + } else if (last == LATCHB || last == SHIFTA) { /* Maintain state */ + list[1][i] = LATCHB; + } else if (next == SHIFTA) { + list[1][i] = LATCHA; + } else { + list[1][i] = LATCHB; + } + } else if (current == SHIFTA) { + if (length > 1) { + /* Rule 4 */ + list[1][i] = LATCHA; + } else if (last == LATCHA || last == SHIFTB) { /* Maintain state */ + list[1][i] = LATCHA; + } else if (last == LATCHC) { + list[1][i] = LATCHA; + } + } else if (current == SHIFTB) { /* Unless LATCHC set above, can only be SHIFTB */ + if (length > 1) { + /* Rule 5 */ + list[1][i] = LATCHB; + } else if (last == LATCHB || last == SHIFTA) { /* Maintain state */ + list[1][i] = LATCHB; + } else if (last == LATCHC) { + list[1][i] = 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 */ + } /* Rule 2 is implemented elsewhere, Rule 6 is implied */ } - grwp(indexliste); + grwp(indexliste); } /** * Translate Code 128 Set A characters into barcodes. - * This set handles all control characters NULL to US. + * This set handles all control characters NUL to US. */ static void c128_set_a(unsigned char source, char dest[], int values[], int *bar_chars) { @@ -288,12 +270,12 @@ static void c128_set_c(unsigned char source_a, unsigned char source_b, char dest (*bar_chars)++; } -/* Handle Code 128 and NVE-18 */ -INTERNAL int code_128(struct zint_symbol *symbol, unsigned char source[], const size_t length) { +/* Handle Code 128, 128B and HIBC 128 */ +INTERNAL int code_128(struct zint_symbol *symbol, const unsigned char source[], const size_t length) { int i, j, k, values[170] = {0}, bar_characters, read, total_sum; int error_number, indexchaine, indexliste, f_state; int sourcelen; - char set[170] = {' '}, fset[170] = {' '}, mode, last_set, current_set = ' '; + char set[170] = {0}, fset[170], mode, last_set, current_set = ' '; float glyph_count; char dest[1000]; @@ -302,7 +284,6 @@ INTERNAL int code_128(struct zint_symbol *symbol, unsigned char source[], const sourcelen = length; - j = 0; bar_characters = 0; f_state = 0; @@ -315,8 +296,7 @@ INTERNAL int code_128(struct zint_symbol *symbol, unsigned char source[], const /* Detect extended ASCII characters */ for (i = 0; i < sourcelen; i++) { - if (source[i] >= 128) - fset[i] = 'f'; + fset[i] = source[i] >= 128 ? 'f' : ' '; } fset[i] = '\0'; @@ -346,10 +326,15 @@ INTERNAL int code_128(struct zint_symbol *symbol, unsigned char source[], const 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 */ + for (j = 0; ((i + j) < sourcelen) && (fset[i + j] == ' '); j++); + /* Count how many 8859-1 beyond */ + k = 0; + if (i + j < sourcelen) { + for (k = 1; ((i + j + k) < sourcelen) && (fset[i + j + k] != ' '); k++); + } + if (j < 3 || (j < 5 && k > 2)) { /* Change to shifting back rather than latching back */ + /* Inverts the same figures recommended by Annex E note 3 */ for (k = 0; k < j; k++) { fset[i + k] = 'n'; } @@ -427,26 +412,14 @@ INTERNAL int code_128(struct zint_symbol *symbol, unsigned char source[], const } } - /* 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'); + if (symbol->debug & ZINT_DEBUG_PRINT) { + printf(" Set: %s (%d)\n", set, (int) strlen(set)); + printf("FSet: %s (%d)\n", fset, (int) strlen(fset)); } /* Now we can calculate how long the barcode is going to be - and stop it from being too long */ - last_set = ' '; + last_set = set[0]; glyph_count = 0.0; for (i = 0; i < sourcelen; i++) { if ((set[i] == 'a') || (set[i] == 'b')) { @@ -537,7 +510,6 @@ INTERNAL int code_128(struct zint_symbol *symbol, unsigned char source[], const } } bar_characters++; - last_set = set[0]; if (fset[0] == 'F') { switch (current_set) { @@ -663,18 +635,33 @@ INTERNAL int code_128(struct zint_symbol *symbol, unsigned char source[], const } while (read < sourcelen); /* check digit calculation */ - total_sum = 0; + total_sum = values[0] % 103; /* Mod as we go along to avoid overflow */ - for (i = 0; i < bar_characters; i++) { - if (i > 0) { - values[i] *= i; - } - total_sum += values[i]; + for (i = 1; i < bar_characters; i++) { + total_sum = (total_sum + values[i] * i) % 103; } - strcat(dest, C128Table[total_sum % 103]); + strcat(dest, C128Table[total_sum]); + values[bar_characters] = total_sum; + bar_characters++; /* Stop character */ strcat(dest, C128Table[106]); + values[bar_characters] = 106; + bar_characters++; + + if (symbol->debug & ZINT_DEBUG_PRINT) { + printf("Codewords:"); + for (i = 0; i < bar_characters; i++) { + printf(" %d", values[i]); + } + printf("\n"); + } +#ifdef ZINT_TEST + if (symbol->debug & ZINT_DEBUG_TEST) { + debug_test_codeword_dump_int(symbol, values, bar_characters); + } +#endif + expand(symbol, dest); return error_number; } @@ -687,16 +674,15 @@ INTERNAL int ean_128(struct zint_symbol *symbol, unsigned char source[], const s float glyph_count; char dest[1000]; int separator_row, linkage_flag, c_count; + int reduced_length; #ifndef _MSC_VER char reduced[length + 1]; #else char* reduced = (char*) _alloca(length + 1); #endif - error_number = 0; strcpy(dest, ""); linkage_flag = 0; - j = 0; bar_characters = 0; separator_row = 0; @@ -721,6 +707,7 @@ INTERNAL int ean_128(struct zint_symbol *symbol, unsigned char source[], const s if (error_number != 0) { return error_number; } + reduced_length = strlen(reduced); /* Decide on mode using same system as PDF417 and rules of ISO 15417 Annex E */ indexliste = 0; @@ -737,7 +724,7 @@ INTERNAL int ean_128(struct zint_symbol *symbol, unsigned char source[], const s do { list[1][indexliste] = mode; - while ((list[1][indexliste] == mode) && (indexchaine < (int) strlen(reduced))) { + while ((list[1][indexliste] == mode) && (indexchaine < reduced_length)) { list[0][indexliste]++; indexchaine++; mode = parunmodd(reduced[indexchaine]); @@ -746,7 +733,7 @@ INTERNAL int ean_128(struct zint_symbol *symbol, unsigned char source[], const s } } indexliste++; - } while (indexchaine < (int) strlen(reduced)); + } while (indexchaine < reduced_length); dxsmooth(&indexliste); @@ -810,11 +797,16 @@ INTERNAL int ean_128(struct zint_symbol *symbol, unsigned char source[], const s } } + if (symbol->debug & ZINT_DEBUG_PRINT) { + printf("Data: %s (%d)\n", reduced, reduced_length); + printf(" Set: %.*s\n", reduced_length, set); + } + /* Now we can calculate how long the barcode is going to be - and stop it from being too long */ - last_set = ' '; + last_set = set[0]; glyph_count = 0.0; - for (i = 0; i < (int) strlen(reduced); i++) { + for (i = 0; i < reduced_length; i++) { if ((set[i] == 'a') || (set[i] == 'b')) { glyph_count = glyph_count + 1.0; } @@ -908,7 +900,7 @@ INTERNAL int ean_128(struct zint_symbol *symbol, unsigned char source[], const s bar_characters++; read++; } - } while (read < (int) strlen(reduced)); + } while (read < reduced_length); /* "...note that the linkage flag is an extra code set character between the last data character and the Symbol Check Character" (GS1 Specification) */ @@ -919,7 +911,7 @@ INTERNAL int ean_128(struct zint_symbol *symbol, unsigned char source[], const s case 1: case 2: /* CC-A or CC-B 2D component */ - switch (set[strlen(reduced) - 1]) { + switch (set[reduced_length - 1]) { case 'A': linkage_flag = 100; break; case 'B': linkage_flag = 99; @@ -930,7 +922,7 @@ INTERNAL int ean_128(struct zint_symbol *symbol, unsigned char source[], const s break; case 3: /* CC-C 2D component */ - switch (set[strlen(reduced) - 1]) { + switch (set[reduced_length - 1]) { case 'A': linkage_flag = 99; break; case 'B': linkage_flag = 101; @@ -948,22 +940,28 @@ INTERNAL int ean_128(struct zint_symbol *symbol, unsigned char source[], const s } /* check digit calculation */ - total_sum = 0; - for (i = 0; i < bar_characters; i++) { - if (i > 0) { - values[i] *= i; + total_sum = values[0] % 103; /* Mod as we go along to avoid overflow */ - } - total_sum += values[i]; + for (i = 1; i < bar_characters; i++) { + total_sum = (total_sum + values[i] * i) % 103; } - strcat(dest, C128Table[total_sum % 103]); - values[bar_characters] = total_sum % 103; + strcat(dest, C128Table[total_sum]); + values[bar_characters] = total_sum; bar_characters++; /* Stop character */ strcat(dest, C128Table[106]); values[bar_characters] = 106; bar_characters++; + + if (symbol->debug & ZINT_DEBUG_PRINT) { + printf("Codewords:"); + for (i = 0; i < bar_characters; i++) { + printf(" %d", values[i]); + } + printf("\n"); + } + expand(symbol, dest); /* Add the separator pattern for composite symbols */ diff --git a/backend/common.c b/backend/common.c index e6bb5d95..6255f800 100644 --- a/backend/common.c +++ b/backend/common.c @@ -206,7 +206,8 @@ INTERNAL void expand(struct zint_symbol *symbol, const char data[]) { symbol->rows = symbol->rows + 1; } -/* Indicates which symbologies can have row binding */ +/* Indicates which symbologies can have row binding + * Note: if change this must also change version in frontend/main.c */ INTERNAL int is_stackable(const int symbology) { if (symbology < BARCODE_PDF417) { return 1; @@ -223,6 +224,7 @@ INTERNAL int is_stackable(const int symbology) { case BARCODE_ITF14: case BARCODE_CODE32: case BARCODE_CODABLOCKF: + case BARCODE_HIBC_BLOCKF: return 1; } diff --git a/backend/library.c b/backend/library.c index abf2a2d1..50281346 100644 --- a/backend/library.c +++ b/backend/library.c @@ -130,7 +130,7 @@ INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int lengt INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int length); /* Deutsche Post Leitcode */ INTERNAL int dpident(struct zint_symbol *symbol, unsigned char source[], int length); /* Deutsche Post Identcode */ INTERNAL int c93(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 93 - a re-working of Code 39+, generates 2 check digits */ -INTERNAL int code_128(struct zint_symbol *symbol, unsigned char source[], const size_t length); /* Code 128 and NVE-18 */ +INTERNAL int code_128(struct zint_symbol *symbol, const unsigned char source[], const size_t length); /* Code 128 and NVE-18 */ INTERNAL int ean_128(struct zint_symbol *symbol, unsigned char source[], const size_t length); /* EAN-128 (GS1-128) */ INTERNAL int code_11(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 11 */ INTERNAL int msi_handle(struct zint_symbol *symbol, unsigned char source[], int length); /* MSI Plessey */ @@ -903,6 +903,10 @@ static int escape_char_process(struct zint_symbol *symbol, unsigned char *input_ do { if (input_string[in_posn] == '\\') { + if (in_posn + 1 >= *length) { + strcpy(symbol->errtxt, "236: Incomplete escape character in input data"); + return ZINT_ERROR_INVALID_DATA; + } switch (input_string[in_posn + 1]) { case '0': escaped_string[out_posn] = 0x00; /* Null */ in_posn += 2; diff --git a/backend/raster.c b/backend/raster.c index 14e5d212..d7373830 100644 --- a/backend/raster.c +++ b/backend/raster.c @@ -1095,7 +1095,7 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int /* Put boundary bars or box around symbol */ if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) { /* boundary bars */ - if (symbol->symbology != BARCODE_CODABLOCKF) { + if (symbol->symbology != BARCODE_CODABLOCKF && symbol->symbology != BARCODE_HIBC_BLOCKF) { draw_bar(pixelbuf, 0, (symbol->width + xoffset + xoffset) * 2, textoffset * 2, symbol->border_width * 2, image_width, image_height, DEFAULT_INK); draw_bar(pixelbuf, 0, (symbol->width + xoffset + xoffset) * 2, (textoffset + symbol->height + symbol->border_width) * 2, symbol->border_width * 2, image_width, image_height, DEFAULT_INK); } else { @@ -1104,15 +1104,19 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int } if ((symbol->output_options & BARCODE_BIND) != 0) { if ((symbol->rows > 1) && (is_stackable(symbol->symbology) == 1)) { + double sep_height = 2; + if (symbol->option_3 > 0 && symbol->option_3 <= 4) { + sep_height = symbol->option_3; + } /* row binding */ - if (symbol->symbology != BARCODE_CODABLOCKF) { + if (symbol->symbology != BARCODE_CODABLOCKF && symbol->symbology != BARCODE_HIBC_BLOCKF) { for (r = 1; r < symbol->rows; r++) { - draw_bar(pixelbuf, xoffset * 2, symbol->width * 2, ((r * row_height) + textoffset + yoffset - 1) * 2, 2 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, xoffset * 2, symbol->width * 2, ((r * row_height) + textoffset + yoffset - sep_height / 2) * 2, sep_height * 2, image_width, image_height, DEFAULT_INK); } } else { for (r = 1; r < symbol->rows; r++) { /* Avoid 11-module start and stop chars */ - draw_bar(pixelbuf, (xoffset + 11) * 2 , (symbol->width - 22) * 2, ((r * row_height) + textoffset + yoffset - 1) * 2, 2 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (xoffset + 11) * 2, (symbol->width - 22) * 2, ((r * row_height) + textoffset + yoffset - sep_height / 2) * 2, sep_height * 2, image_width, image_height, DEFAULT_INK); } } } diff --git a/backend/tests/test_codablock.c b/backend/tests/test_codablock.c index 4aa6420e..b2046ec3 100644 --- a/backend/tests/test_codablock.c +++ b/backend/tests/test_codablock.c @@ -31,23 +31,33 @@ #include "testcommon.h" -static void test_options(int index, int debug) { +static void test_large(int index, int debug) { testStart(""); int ret; struct item { - int option_1; - int option_2; - unsigned char *data; + unsigned char *pattern; + int length; int ret; - char *comment; + int expected_rows; + int expected_width; }; + // é U+00E9 (\351, 233), UTF-8 C3A9, CodeB-only extended ASCII // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { - /* 0*/ { -1, -1, "é", 0, "" }, + /* 0*/ { "A", 2666, 0, 44, 728 }, + /* 1*/ { "A", 2725, 0, 44, 739 }, + /* 2*/ { "A", 2726, 0, 44, 739 }, // 4.2.1 c.3 says max 2725 but actually 44 * 62 - 2 == 2726 as mentioned later in 4.8.1 + /* 3*/ { "A", 2727, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 4*/ { "12", 2726 * 2, 0, 44, 739 }, + /* 5*/ { "12", 2726 * 2 + 1, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 6*/ { "\351", 2726 / 2, 0, 44, 739 }, + /* 7*/ { "\351", 2726 / 2 + 1, ZINT_ERROR_TOO_LONG, -1, -1 }, }; - int data_size = sizeof(data) / sizeof(struct item); + int data_size = ARRAY_SIZE(data); + + char data_buf[2726 * 2 + 2]; for (int i = 0; i < data_size; i++) { @@ -56,19 +66,249 @@ static void test_options(int index, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - symbol->symbology = BARCODE_CODABLOCKF; - if (data[i].option_1 != -1) { - symbol->option_1 = data[i].option_1; - } - if (data[i].option_2 != -1) { - symbol->option_2 = data[i].option_2; - } - symbol->debug |= debug; + testUtilStrCpyRepeat(data_buf, data[i].pattern, data[i].length); + assert_equal(data[i].length, (int) strlen(data_buf), "i:%d length %d != strlen(data_buf) %d\n", i, data[i].length, (int) strlen(data_buf)); - int length = strlen(data[i].data); + int length = testUtilSetSymbol(symbol, BARCODE_CODABLOCKF, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data_buf, data[i].length, debug); + + ret = ZBarcode_Encode(symbol, data_buf, length); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (ret < 5) { + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width); + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_options(int index, int debug) { + + testStart(""); + + int ret; + struct item { + int input_mode; + int option_1; + int option_2; + unsigned char *data; + int ret; + int expected_rows; + int expected_width; + char *comment; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { UNICODE_MODE, 1, -1, "é", 0, 1, 57, "CODE128" }, + /* 1*/ { UNICODE_MODE, -1, -1, "A", 0, 2, 101, "Defaults" }, + /* 2*/ { UNICODE_MODE, 0, -1, "A", 0, 2, 101, "0 rows same as -1" }, + /* 3*/ { UNICODE_MODE, 2, -1, "A", 0, 2, 101, "Rows 2, columns default" }, + /* 4*/ { UNICODE_MODE, 3, -1, "A", 0, 3, 101, "Rows 3" }, + /* 5*/ { UNICODE_MODE, 43, -1, "A", 0, 43, 101, "Rows 43" }, + /* 6*/ { UNICODE_MODE, 44, -1, "A", 0, 44, 101, "Max rows" }, + /* 7*/ { UNICODE_MODE, 45, -1, "A", ZINT_ERROR_INVALID_OPTION, -1, -1, "" }, + /* 8*/ { UNICODE_MODE, -1, -1, "abcdefg", 0, 3, 101, "" }, + /* 9*/ { UNICODE_MODE, 2, -1, "abcdefg", 0, 2, 112, "Rows given so columns expanded" }, + /* 10*/ { UNICODE_MODE, 3, -1, "abcdefg", 0, 3, 101, "" }, + /* 11*/ { UNICODE_MODE, -1, 8, "A", ZINT_ERROR_INVALID_OPTION, -1, -1, "Min columns 9 (4 data)" }, + /* 12*/ { UNICODE_MODE, -1, 9, "A", 0, 2, 101, "Min columns 9 (4 data)" }, + /* 13*/ { UNICODE_MODE, -1, 10, "A", 0, 2, 112, "Columns 10" }, + /* 14*/ { UNICODE_MODE, -1, 66, "A", 0, 2, 728, "Columns 66" }, + /* 15*/ { UNICODE_MODE, -1, 67, "A", 0, 2, 739, "Max columns 67 (62 data)" }, + /* 16*/ { UNICODE_MODE, -1, 68, "A", ZINT_ERROR_INVALID_OPTION, -1, -1, "" }, + /* 17*/ { UNICODE_MODE, 2, 9, "A", 0, 2, 101, "Rows and columns defaults given" }, + /* 18*/ { UNICODE_MODE, 2, 10, "A", 0, 2, 112, "Rows and columns given" }, + /* 19*/ { UNICODE_MODE, 3, 11, "A", 0, 3, 123, "" }, + /* 20*/ { UNICODE_MODE, 43, 66, "A", 0, 43, 728, "" }, + /* 21*/ { UNICODE_MODE, 44, 67, "A", 0, 44, 739, "Max rows, max columns" }, + /* 22*/ { GS1_MODE, -1, -1, "A", ZINT_ERROR_INVALID_OPTION, -1, -1, "GS1 not supported" }, + /* 23*/ { GS1_MODE, 1, -1, "A", ZINT_ERROR_INVALID_OPTION, -1, -1, "Check for CODE128" }, + }; + int data_size = ARRAY_SIZE(data); + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + int length = testUtilSetSymbol(symbol, BARCODE_CODABLOCKF, data[i].input_mode, -1 /*eci*/, data[i].option_1, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, data[i].data, length); - assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d\n", i, ret, data[i].ret); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (ret < 5) { + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_reader_init(int index, int generate, int debug) { + + testStart(""); + + int ret; + struct item { + int symbology; + int input_mode; + int output_options; + unsigned char *data; + int ret; + int expected_rows; + int expected_width; + char *expected; + char *comment; + }; + struct item data[] = { + /* 0*/ { BARCODE_CODABLOCKF, UNICODE_MODE, 16, "1234", 0, 2, 101, "67 64 40 60 63 0C 22 2B 6A 67 64 0B 63 64 3A 1C 29 6A", "CodeB FNC3 CodeC 12 34 / CodeB Pads" }, + /* 1*/ { BARCODE_HIBC_BLOCKF, UNICODE_MODE, 16, "123456", 0, 3, 101, "67 64 41 60 0B 11 12 22 6A 67 63 2B 22 38 64 2A 1B 6A 67 64 0C 63 64 2B 2F 52 6A", "CodeB FNC3 + 1 2 / CodeC 34 56 CodeB J" }, + }; + int data_size = ARRAY_SIZE(data); + + char escaped[1024]; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + symbol->debug = ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt + + int length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1 /*option_2*/, -1, data[i].output_options, data[i].data, -1, debug); + + ret = ZBarcode_Encode(symbol, data[i].data, length); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (generate) { + printf(" /*%3d*/ { %s, %s, %d, \"%s\", %s, %d, %d, \"%s\", \"%s\" },\n", + i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), data[i].output_options, + testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, symbol->errtxt, data[i].comment); + } else { + if (ret < 5) { + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); + assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + } + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_input(int index, int generate, int debug) { + + testStart(""); + + int ret; + struct item { + int symbology; + int input_mode; + int option_2; + unsigned char *data; + int length; + int ret; + int expected_rows; + int expected_width; + char *expected; + char *comment; + }; + // NUL U+0000, CodeA-only + // US U+001F (\037, 31), CodeA-only + // a U+0061 (\141, 97), CodeB-only + // DEL U+007F (\177, 127), CodeB-only + // PAD U+0080 (\200, 128), UTF-8 C280 (\302\200), CodeA-only extended ASCII, not in ISO 8859-1 + // APC U+009F (\237, 159), UTF-8 C29F, CodeA-only extended ASCII, not in ISO 8859-1 + // NBSP U+00A0 (\240, 160), UTF-8 C2A0, CodeA and CodeB extended ASCII + // ß U+00DF (\337, 223), UTF-8 C39F, CodeA and CodeB extended ASCII + // à U+00E0 (\340, 224), UTF-8 C3A0, CodeB-only extended ASCII + // á U+00E1 (\341, 225), UTF-8 C3A1, CodeB-only extended ASCII + // é U+00E9 (\351, 233), UTF-8 C3A9, CodeB-only extended ASCII + // ñ U+00F1 (\361, 241), UTF-8 C3B1, CodeB-only extended ASCII + // ÿ U+00FF (\377, 255), UTF-8 C3BF, CodeB-only extended ASCII + struct item data[] = { + /* 0*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "A", -1, 0, 2, 101, "67 64 40 21 63 64 63 42 6A 67 64 0B 63 64 2B 40 4F 6A", "Fillings 5" }, + /* 1*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "AAA", -1, 0, 2, 101, "67 64 40 21 21 21 63 55 6A 67 64 0B 63 64 0E 57 48 6A", "Fillings 3" }, + /* 2*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "AAAA", -1, 0, 2, 101, "67 64 40 21 21 21 21 65 6A 67 64 0B 63 64 1A 0E 03 6A", "Fillings 2" }, + /* 3*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "AAAAA", -1, 0, 2, 101, "67 64 40 21 21 21 21 65 6A 67 64 0B 21 63 1D 30 14 6A", "Fillings 1" }, + /* 4*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "AAAAAA", -1, 0, 2, 101, "67 64 40 21 21 21 21 65 6A 67 64 0B 21 21 35 5D 2B 6A", "Fillings 0" }, + /* 5*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "1234", -1, 0, 2, 101, "67 63 00 0C 22 64 63 1A 6A 67 64 0B 63 64 3A 1C 29 6A", "Fillings 4" }, + /* 6*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "12345", -1, 0, 2, 101, "67 63 00 0C 22 64 15 49 6A 67 64 0B 63 64 41 44 07 6A", "Fillings 2 (not counting CodeB at end of 1st line)" }, + /* 7*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "123456", -1, 0, 2, 101, "67 63 00 0C 22 38 64 12 6A 67 64 0B 63 64 2D 50 52 6A", "Fillings 3" }, + /* 8*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "1234567", -1, 0, 2, 101, "67 63 00 0C 22 38 64 12 6A 67 64 0B 17 63 16 02 5B 6A", "Fillings 1 (not counting CodeB at end of 1st line)" }, + /* 9*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "12345678", -1, 0, 2, 101, "67 63 00 0C 22 38 4E 5C 6A 67 64 0B 63 64 08 1C 64 6A", "Fillings 2" }, + /* 10*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "123456789", -1, 0, 2, 101, "67 63 00 0C 22 38 4E 5C 6A 67 64 0B 19 63 25 4C 65 6A", "Fillings 1" }, + /* 11*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "1234567890", -1, 0, 2, 101, "67 63 00 0C 22 38 4E 5C 6A 67 64 0B 19 10 41 38 62 6A", "Fillings 0" }, + /* 12*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "A123ñ", -1, 0, 2, 101, "67 64 40 21 11 12 13 54 6A 67 64 0B 64 51 42 28 50 6A", "K1/K2 example in Annex F" }, + /* 13*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "aß", -1, 0, 2, 101, "67 64 40 41 64 3F 63 54 6A 67 64 0B 63 64 5B 1D 06 6A", "CodeB a FNC4 ß fits 1st line" }, + /* 14*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "\037ß", -1, 0, 2, 101, "67 62 40 5F 65 3F 63 49 6A 67 64 0B 63 64 0F 1D 26 6A", "CodeA US FNC4 ß fits 1st line" }, + /* 15*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "aaß", -1, 0, 2, 101, "67 64 40 41 41 64 3F 10 6A 67 64 0B 63 64 4E 5B 04 6A", "CodeB a a FNC4 ß fits 1st line" }, + /* 16*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "\037\037ß", -1, 0, 2, 101, "67 62 40 5F 5F 65 3F 17 6A 67 64 0B 63 64 34 0F 24 6A", "CodeA US US FNC4 ß fits 1st line" }, + /* 17*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "aaaß", -1, 0, 2, 101, "67 64 40 41 41 41 63 39 6A 67 64 0B 64 3F 4C 4E 50 6A", "CodeB a (3) / CodeB FNC4 ß fully on next line" }, + /* 18*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "\037\037\037ß", -1, 0, 2, 101, "67 62 40 5F 5F 5F 63 03 6A 67 64 0B 64 3F 0E 34 1A 6A", "CodeA US (3) / CodeB FNC4 ß fully on next line" }, + /* 19*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "aà", -1, 0, 2, 101, "67 64 40 41 64 40 63 59 6A 67 64 0B 63 64 5D 1E 16 6A", "CodeB a FNC4 à fits 1st line" }, + /* 20*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "\037à", -1, 0, 2, 101, "67 62 40 5F 65 62 40 26 6A 67 64 0B 63 64 1B 1E 01 6A", "CodeA US FNC4 Shift à fits 1st line" }, + /* 21*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "\037àa", -1, 0, 2, 101, "67 62 40 5F 64 64 40 2C 6A 67 64 0B 41 63 52 4A 16 6A", "CodeA US LatchB FNC4 à fits 1st line / Code B a" }, + /* 22*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "aaà", -1, 0, 2, 101, "67 64 40 41 41 64 40 16 6A 67 64 0B 63 64 51 5D 1F 6A", "CodeB a a FNC4 à fits 1st line" }, + /* 23*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "\037\037à", -1, 0, 2, 101, "67 62 40 5F 5F 63 64 1D 6A 67 64 0B 64 40 37 1B 55 6A", "CodeA US US / Code B FNC4 à fully on next line" }, + /* 24*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "aaaà", -1, 0, 2, 101, "67 64 40 41 41 41 63 39 6A 67 64 0B 64 40 50 51 13 6A", "CodeB a (3) / Code B FNC4 à fully on next line" }, + /* 25*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "\037\037\037à", -1, 0, 2, 101, "67 62 40 5F 5F 5F 63 03 6A 67 64 0B 64 40 1C 37 0F 6A", "CodeA US (3) / CodeB FNC4 à fully on next line" }, + /* 26*/ { BARCODE_CODABLOCKF, DATA_MODE, -1, "\037\200", -1, 0, 2, 101, "67 62 40 5F 65 40 63 4E 6A 67 64 0B 63 64 5D 0A 05 6A", "CodeA US FNC4 PAD fits 1st line" }, + /* 27*/ { BARCODE_CODABLOCKF, DATA_MODE, -1, "\141\200", -1, 0, 2, 101, "67 64 40 41 64 62 40 31 6A 67 64 0B 63 64 49 0A 08 6A", "CodeB a FNC4 Shift PAD fits 1st line" }, + /* 28*/ { BARCODE_CODABLOCKF, DATA_MODE, -1, "\141\200\037", -1, 0, 2, 101, "67 64 40 41 65 65 40 44 6A 67 62 0B 5F 63 10 12 3E 6A", "CodeB a LatchA FNC4 PAD fits 1st line / CodeA US" }, + /* 29*/ { BARCODE_CODABLOCKF, DATA_MODE, -1, "\037\037\200", -1, 0, 2, 101, "67 62 40 5F 5F 65 40 1D 6A 67 64 0B 63 64 0F 5D 0A 6A", "CodeA US US FNC4 PAD fits 1st line" }, + /* 30*/ { BARCODE_CODABLOCKF, DATA_MODE, -1, "\141\141\200", -1, 0, 2, 101, "67 64 40 41 41 63 64 1B 6A 67 62 0B 65 40 33 49 21 6A", "CodeB a a / CodeA FNC4 PAD fully on next line" }, + /* 31*/ { BARCODE_CODABLOCKF, DATA_MODE, -1, "\037\037\037\200", -1, 0, 2, 101, "67 62 40 5F 5F 5F 63 03 6A 67 62 0B 65 40 4A 0F 06 6A", "CodeA US (3) / CodeA FNC4 PAD fully on next line" }, + /* 32*/ { BARCODE_CODABLOCKF, DATA_MODE, -1, "\141\141\141\200", -1, 0, 2, 101, "67 64 40 41 41 41 63 39 6A 67 62 0B 65 40 28 33 34 6A", "CodeB a (3) / CodeA FNC4 PAD fully on next line" }, + /* 33*/ { BARCODE_CODABLOCKF, DATA_MODE, 10, "\200\240\237\340\337\341\377", -1, 0, 4, 112, "(40) 67 62 42 65 40 65 00 63 1E 6A 67 62 0B 65 5F 64 64 40 55 6A 67 64 0C 64 3F 64 41 63", "" }, + /* 34*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "\000a\037\177}12", 7, 0, 3, 101, "67 62 41 40 62 41 5F 3B 6A 67 64 0B 5F 5D 11 12 2D 6A 67 64 0C 63 64 40 05 26 6A", "" }, + /* 35*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "abcdéf", -1, 0, 3, 101, "67 64 41 41 42 43 44 5D 6A 67 64 0B 64 49 46 63 0A 6A 67 64 0C 63 64 4F 26 02 6A", "" }, + /* 36*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, "a12é\000", 6, 0, 3, 101, "67 64 41 41 11 12 63 2C 6A 67 64 0B 64 49 62 40 2B 6A 67 64 0C 63 64 33 34 31 6A", "" }, + /* 37*/ { BARCODE_HIBC_BLOCKF, UNICODE_MODE, -1, "A99912345/$$52001510X3", -1, 0, 6, 101, "(54) 67 64 44 0B 21 19 19 3A 6A 67 63 2B 5B 17 2D 64 24 6A 67 64 0C 0F 04 04 15 16 6A 67", "" }, + }; + int data_size = ARRAY_SIZE(data); + + char escaped[1024]; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + symbol->debug = ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt + + int length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); + + ret = ZBarcode_Encode(symbol, data[i].data, length); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (generate) { + printf(" /*%3d*/ { %s, %s, %d, \"%s\", %d, %s, %d, %d, \"%s\", \"%s\" },\n", + i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), data[i].option_2, + testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].length, + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, symbol->errtxt, data[i].comment); + } else { + if (ret < 5) { + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); + assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + } + } ZBarcode_Delete(symbol); } @@ -82,7 +322,7 @@ static void test_encode(int index, int generate, int debug) { int ret; struct item { - int input_mode; + int symbology; int option_1; int option_2; unsigned char *data; @@ -94,39 +334,81 @@ static void test_encode(int index, int generate, int debug) { char *expected; }; struct item data[] = { - /* 0*/ { UNICODE_MODE, -1, -1, "AIM", 0, 1, 68, "Same as CODE128", + /* 0*/ { BARCODE_CODABLOCKF, 1, -1, "AIM", 0, 1, 68, "Same as CODE128", "11010010000101000110001100010001010111011000101110110001100011101011" - }, - /* 1*/ { UNICODE_MODE, -1, -1, "AAAAAAAAA", 0, 4, 90, "", - "110100001001011110111010010000110101000110001010001100010100011000110010001001100011101011" - "110100001001011110111011000100100101000110001010001100010100011000100100110001100011101011" - "110100001001011110111010110011100101000110001010001100010100011000100010011001100011101011" - "110100001001011101111010111011000101111011101001011000010010011110111001001101100011101011" - }, - /* 2*/ { UNICODE_MODE, 3, -1, "AAAAAAAAA", 0, 3, 101, "Verified manually against tec-it (bwipp differs)", + }, + /* 1*/ { BARCODE_CODABLOCKF, -1, -1, "AAAAAAA", 0, 3, 101, "Defaults to rows 3, columns 9 (4 data); verified manually against bwipp and tec-it", + "11010000100101111011101001011000010100011000101000110001010001100010100011000110110011001100011101011" + "11010000100101111011101100010010010100011000101000110001010001100010111011110100100111101100011101011" + "11010000100101111011101011001110010111011110101111011101100001010011011101110111100101001100011101011" + }, + /* 2*/ { BARCODE_CODABLOCKF, -1, -1, "AAAAAAAAAA", 0, 3, 101, "Defaults to rows 3, columns 9 (4 data); verified manually against bwipp and tec-it", "11010000100101111011101001011000010100011000101000110001010001100010100011000110110011001100011101011" "11010000100101111011101100010010010100011000101000110001010001100010100011000111101000101100011101011" - "11010000100101111011101011001110010100011000101110111101100110110011001110010110001001001100011101011" - }, - /* 3*/ { UNICODE_MODE, -1, -1, "AAAAAAAAAAAAAAA", 0, 6, 90, "", - "110100001001011110111010000100110101000110001010001100010100011000100110011101100011101011" - "110100001001011110111011000100100101000110001010001100010100011000100100110001100011101011" - "110100001001011110111010110011100101000110001010001100010100011000100010011001100011101011" - "110100001001011110111010011011100101000110001010001100010100011000100110001001100011101011" - "110100001001011110111010011001110101000110001010001100010100011000110010010001100011101011" - "110100001001011101111010001110110101111011101000110001010111101000110111101101100011101011" - }, - /* 4*/ { UNICODE_MODE, -1, 14, "AAAAAAAAAAAAAAA", 0, 2, 156, "", + "11010000100101111011101011001110010100011000101000110001110110010010010110000111000101101100011101011" + }, + /* 3*/ { BARCODE_CODABLOCKF, -1, -1, "AAAAAAAAAAA", 0, 4, 101, "Defaults to rows 4, columns 9 (4 data); verified manually against bwipp and tec-it", + "11010000100101111011101001000011010100011000101000110001010001100010100011000110011001101100011101011" + "11010000100101111011101100010010010100011000101000110001010001100010100011000111101000101100011101011" + "11010000100101111011101011001110010100011000101000110001010001100010111011110100111101001100011101011" + "11010000100101111011101001101110010111011110101111011101110101100011101100100110010111001100011101011" + }, + /* 4*/ { BARCODE_CODABLOCKF, -1, -1, "AAAAAAAAAAAAAA", 0, 4, 101, "Defaults to rows 4, columns 9 (4 data); verified manually against bwipp and tec-it", + "11010000100101111011101001000011010100011000101000110001010001100010100011000110011001101100011101011" + "11010000100101111011101100010010010100011000101000110001010001100010100011000111101000101100011101011" + "11010000100101111011101011001110010100011000101000110001010001100010100011000101111011101100011101011" + "11010000100101111011101001101110010100011000101000110001011110100010111011000100110000101100011101011" + }, + /* 5*/ { BARCODE_CODABLOCKF, -1, -1, "AAAAAAAAAAAAAAA", 0, 5, 101, "Defaults to rows 5, columns 9 (4 data); verified manually against bwipp (columns=4) and tec-it", + "11010000100101111011101000010110010100011000101000110001010001100010100011000100100011001100011101011" + "11010000100101111011101100010010010100011000101000110001010001100010100011000111101000101100011101011" + "11010000100101111011101011001110010100011000101000110001010001100010100011000101111011101100011101011" + "11010000100101111011101001101110010100011000101000110001010001100010111011110111101001001100011101011" + "11010000100101111011101001100111010111011110101111011101000110001010111101000110001010001100011101011" + }, + /* 6*/ { BARCODE_CODABLOCKF, -1, 14, "AAAAAAAAAAAAAAA", 0, 2, 156, "Rows 2, columns 14 (9 data); verified manually against bwipp (columns=9) and tec-it", "110100001001011110111010100001100101000110001010001100010100011000101000110001010001100010100011000101000110001010001100010100011000110001000101100011101011" "110100001001011110111011000100100101000110001010001100010100011000101000110001010001100010100011000101110111101110111101011011000110111000101101100011101011" - }, - /* 5*/ { UNICODE_MODE, 3, -1, "AAAAAAAAAAAAAAA", 0, 3, 123, "Differs from tec-it (and bwipp); TODO: verify", - "110100001001011110111010010110000101000110001010001100010100011000101000110001010001100010100011000101111001001100011101011" - "110100001001011110111011000100100101000110001010001100010100011000101000110001010001100010100011000110000101001100011101011" - "110100001001011110111010110011100101000110001010001100010100011000101110111101110111101011011000110110110001101100011101011" - }, + }, + /* 7*/ { BARCODE_CODABLOCKF, -1, -1, "AAAAAAAAAAAAAAAA", 0, 5, 101, "Defaults to rows 5, columns 9 (4 data); verified manually against bwipp (columns=4) and tec-it", + "11010000100101111011101000010110010100011000101000110001010001100010100011000100100011001100011101011" + "11010000100101111011101100010010010100011000101000110001010001100010100011000111101000101100011101011" + "11010000100101111011101011001110010100011000101000110001010001100010100011000101111011101100011101011" + "11010000100101111011101001101110010100011000101000110001010001100010100011000111101011101100011101011" + "11010000100101111011101001100111010111011110101111011101011100011010001100010100011101101100011101011" + }, + /* 8*/ { BARCODE_CODABLOCKF, -1, -1, "AAAAAAAAAAAAAAAAAAAAAAAAA", 0, 6, 112, "Defaults to rows 6, columns 10 (5 data); verified manually against bwipp (columns=5) and tec-it", + "1101000010010111101110100001001101010001100010100011000101000110001010001100010100011000110110001101100011101011" + "1101000010010111101110110001001001010001100010100011000101000110001010001100010100011000110010011101100011101011" + "1101000010010111101110101100111001010001100010100011000101000110001010001100010100011000110011101001100011101011" + "1101000010010111101110100110111001010001100010100011000101000110001010001100010100011000111010011001100011101011" + "1101000010010111101110100110011101010001100010100011000101000110001010001100010100011000111001001101100011101011" + "1101000010010111101110101110011001011101111010111101110101110111101110100011010100001100110001010001100011101011" + }, + /* 9*/ { BARCODE_CODABLOCKF, 4, -1, "CODABLOCK F 34567890123456789010040digit", 0, 4, 145, "AIM ISS-X-24 Figure 1", + "1101000010010111101110100100001101000100011010001110110101100010001010001100010001011000100011011101000111011010001000110110110011001100011101011" + "1101000010010111101110110001001001011000111011011001100100011000101101100110010111011110100010110001110001011011000010100101100111001100011101011" + "1101000010010111011110100011011101101111011010110011100100010110001110001011011000010100110111101101100100010010010001100100011000101100011101011" + "1101000010010111101110100110111001001110110010000100110100001101001001101000010000110100100111101001101110111010111000110110010000101100011101011" + }, + /* 10*/ { BARCODE_CODABLOCKF, 3, -1, "CODABLOCK F Symbology", 0, 3, 145, "AIM ISS-X-24 Figure on front page", + "1101000010010111101110100101100001000100011010001110110101100010001010001100010001011000100011011101000111011010001000110111010111101100011101011" + "1101000010010111101110110001001001011000111011011001100100011000101101100110011011101000110110111101111011101010010000110100100111101100011101011" + "1101000010010111101110101100111001000111101011001010000100011110101001101000011011011110101110111101000011001011011101110101001111001100011101011" + }, + /* 11*/ { BARCODE_HIBC_BLOCKF, 3, -1, "A123BJC5D6E71", 0, 3, 123, "Verified manually against tec-it; differs from bwipp (columns=6) which uses Code C for final 71 (same no. of codewords)", + "110100001001011110111010010110000110001001001010001100010011100110110011100101100101110010001011000100100001101100011101011" + "110100001001011110111011000100100101101110001000100011011011100100101100010001100111010010001101000111001001101100011101011" + "110100001001011110111010110011100111011011101001110011011010001000101110111101011100011011001110100100100110001100011101011" + }, + /* 12*/ { BARCODE_HIBC_BLOCKF, -1, -1, "$$52001510X3G", 0, 4, 101, "Verified manually against bwipp (columns=4); tec-it differs as adds unnecessary Code C at end of 1st line", + "11010000100101111011101001000011011000100100100100011001001000110011011100100101110011001100011101011" + "11010000100101110111101011000111011001001110110011011001101110100010111101110100001100101100011101011" + "11010000100101111011101011001110010011101100111000101101100101110011010001000100100011001100011101011" + "11010000100101111011101001101110010110001000101110111101101000111011000110110100011010001100011101011" + }, }; - int data_size = sizeof(data) / sizeof(struct item); + int data_size = ARRAY_SIZE(data); char escaped[1024]; @@ -137,27 +419,17 @@ static void test_encode(int index, int generate, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - symbol->symbology = BARCODE_CODABLOCKF; - symbol->input_mode = data[i].input_mode; - if (data[i].option_1 != -1) { - symbol->option_1 = data[i].option_1; - } - if (data[i].option_2 != -1) { - symbol->option_2 = data[i].option_2; - } - symbol->debug |= debug; - - int length = strlen(data[i].data); + int length = testUtilSetSymbol(symbol, data[i].symbology, UNICODE_MODE, -1 /*eci*/, data[i].option_1, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { printf(" /*%3d*/ { %s, %d, %d, \"%s\", %s, %d, %d, \"%s\",\n", - i, testUtilInputModeName(data[i].input_mode), data[i].option_1, data[i].option_2, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), + i, testUtilBarcodeName(data[i].symbology), data[i].option_1, data[i].option_2, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment); testUtilModulesDump(symbol, " ", "\n"); - printf(" },\n"); + printf(" },\n"); } else { if (ret < 5) { assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); @@ -201,13 +473,7 @@ static void test_fuzz(int index, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - symbol->symbology = BARCODE_CODABLOCKF; - symbol->debug |= debug; - - int length = data[i].length; - if (length == -1) { - length = strlen(data[i].data); - } + int length = testUtilSetSymbol(symbol, BARCODE_CODABLOCKF, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); ret = ZBarcode_Encode(symbol, data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); @@ -221,7 +487,10 @@ static void test_fuzz(int index, int debug) { int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ + { "test_large", test_large, 1, 0, 1 }, { "test_options", test_options, 1, 0, 1 }, + { "test_reader_init", test_reader_init, 1, 1, 1 }, + { "test_input", test_input, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 }, { "test_fuzz", test_fuzz, 1, 0, 1 }, }; diff --git a/backend/tests/test_code128.c b/backend/tests/test_code128.c index 2b87c59a..837ffd6d 100644 --- a/backend/tests/test_code128.c +++ b/backend/tests/test_code128.c @@ -29,9 +29,76 @@ */ /* vim: set ts=4 sw=4 et : */ +/* Note BARCODE_EAN128, BARCODE_EAN14, BARCODE_NVE18 also tested in test_gs1.c */ + #include "testcommon.h" -static void test_input(int index, int debug) { +static void test_large(int index, int debug) { + + testStart(""); + + int ret; + struct item { + int symbology; + unsigned char *pattern; + int length; + int ret; + int expected_width; + }; + // é U+00E9 (\351, 233), UTF-8 C3A9, CodeB-only extended ASCII + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { BARCODE_CODE128, "A", 60, 0, 695 }, + /* 1*/ { BARCODE_CODE128, "A", 61, ZINT_ERROR_TOO_LONG, -1 }, + /* 2*/ { BARCODE_CODE128, "\351A", 40, 0, 695 }, + /* 3*/ { BARCODE_CODE128, "\351A", 41, ZINT_ERROR_TOO_LONG, -1 }, // 41 chars (+ 20 shifts) + /* 4*/ { BARCODE_CODE128, "0", 120, 0, 695 }, + /* 5*/ { BARCODE_CODE128, "0", 121, ZINT_ERROR_TOO_LONG, -1 }, + /* 6*/ { BARCODE_CODE128B, "A", 60, 0, 695 }, + /* 7*/ { BARCODE_CODE128B, "A", 61, ZINT_ERROR_TOO_LONG, -1 }, + /* 8*/ { BARCODE_CODE128B, "0", 60, 0, 695 }, + /* 9*/ { BARCODE_CODE128B, "0", 61, ZINT_ERROR_TOO_LONG, -1 }, + /* 10*/ { BARCODE_EAN128, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]1234567890", -1, 0, 706 }, // 116 nos + 3 FNC1s + /* 11*/ { BARCODE_EAN128, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]1234[93]1234", -1, ZINT_ERROR_TOO_LONG, -1 }, // 116 nos + 4 FNC1s + /* 12*/ { BARCODE_EAN14, "1234567890123", -1, 0, 134 }, + /* 13*/ { BARCODE_EAN14, "12345678901234", -1, ZINT_ERROR_TOO_LONG, -1 }, + /* 14*/ { BARCODE_NVE18, "12345678901234567", -1, 0, 156 }, + /* 15*/ { BARCODE_NVE18, "123456789012345678", -1, ZINT_ERROR_TOO_LONG, -1 }, + }; + int data_size = ARRAY_SIZE(data); + + char data_buf[4096]; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + if (data[i].length != -1) { + testUtilStrCpyRepeat(data_buf, data[i].pattern, data[i].length); + assert_equal(data[i].length, (int) strlen(data_buf), "i:%d length %d != strlen(data_buf) %d\n", i, data[i].length, (int) strlen(data_buf)); + } else { + strcpy(data_buf, data[i].pattern); + } + + int length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data_buf, data[i].length, debug); + + ret = ZBarcode_Encode(symbol, data_buf, length); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (ret < 5) { + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width); + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_hrt(int index, int debug) { testStart(""); @@ -41,18 +108,164 @@ static void test_input(int index, int debug) { int input_mode; unsigned char *data; int length; - int ret; + + unsigned char *expected; }; + // é U+00E9 (\351, 233), UTF-8 C3A9, CodeB-only extended ASCII // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { - /* 0*/ { BARCODE_CODE128, UNICODE_MODE, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", -1, 0 }, // 59 chars - /* 1*/ { BARCODE_CODE128, UNICODE_MODE, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", -1, ZINT_ERROR_TOO_LONG }, // 60 chars - /* 2*/ { BARCODE_CODE128, UNICODE_MODE, "éAéAéAéAéAéAéAéAéAéAéAéAéAéAéAéAéAéAéAé", -1, 0 }, // 39 chars - /* 3*/ { BARCODE_CODE128, UNICODE_MODE, "éAéAéAéAéAéAéAéAéAéAéAéAéAéAéAéAéAéAéAéA", -1, ZINT_ERROR_TOO_LONG }, // 40 chars (+ 20 shifts) - /* 4*/ { BARCODE_CODE128, UNICODE_MODE, "\302\200", -1, ZINT_ERROR_INVALID_DATA }, // PAD U+0080, not in ISO 8859-1 although encodable in CODE128 - /* 5*/ { BARCODE_CODE128, DATA_MODE, "\302\200", -1, 0 }, // PAD U+0080, use binary - /* 6*/ { BARCODE_CODE128, UNICODE_MODE, "\000\037é", 4, 0 }, - /* 7*/ { BARCODE_CODE128B, UNICODE_MODE, "\000\037é", 4, 0 }, + /* 0*/ { BARCODE_CODE128, UNICODE_MODE, "1234567890", -1, "1234567890" }, + /* 1*/ { BARCODE_CODE128, UNICODE_MODE, "\000ABC\000DEF\000", 9, " ABC DEF " }, + /* 2*/ { BARCODE_CODE128B, UNICODE_MODE, "12345\00067890", 11, "12345 67890" }, + /* 3*/ { BARCODE_CODE128, UNICODE_MODE, "12345\01167890\037\177", -1, "12345\01167890\037\177" }, + /* 4*/ { BARCODE_CODE128, UNICODE_MODE, "abcdé", -1, "abcdé" }, + /* 5*/ { BARCODE_CODE128, DATA_MODE, "abcd\351", -1, "abcd\351" }, + /* 6*/ { BARCODE_CODE128B, UNICODE_MODE, "abcdé", -1, "abcdé" }, + /* 7*/ { BARCODE_CODE128B, DATA_MODE, "abcd\351", -1, "abcd\351" }, + // BARCODE_EAN128, BARCODE_EAN14, BARCODE_NVE18 hrt tested in test_gs1.c + }; + int data_size = ARRAY_SIZE(data); + + char *text; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + int length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); + + ret = ZBarcode_Encode(symbol, data[i].data, length); + assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); + + assert_zero(strcmp(symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_reader_init(int index, int generate, int debug) { + + testStart(""); + + int ret; + struct item { + int symbology; + int input_mode; + int output_options; + unsigned char *data; + int ret; + int expected_rows; + int expected_width; + char *expected; + char *comment; + }; + struct item data[] = { + /* 0*/ { BARCODE_CODE128, UNICODE_MODE, 16, "A", 0, 1, 57, "(5) 104 96 33 60 106", "StartA FNC3 A" }, + /* 1*/ { BARCODE_CODE128, UNICODE_MODE, 16, "12", 0, 1, 68, "(6) 104 96 99 12 22 106", "StartB FNC3 CodeC 12" }, + /* 2*/ { BARCODE_CODE128B, UNICODE_MODE, 16, "\0371234", 0, 1, 101, "(9) 103 96 95 17 18 19 20 6 106", "StartA FNC3 US 1 2 3 4" }, + /* 3*/ { BARCODE_EAN128, GS1_MODE, 16, "[90]12", 0, 1, 68, "", "Reader Initialise not supported by GS1 barcodes (use CODE128)" }, + /* 4*/ { BARCODE_EAN14, GS1_MODE, 16, "12", 0, 1, 134, "", "Reader Initialise not supported by GS1 barcodes (use CODE128)" }, + /* 5*/ { BARCODE_NVE18, GS1_MODE, 16, "12", 0, 1, 156, "", "Reader Initialise not supported by GS1 barcodes (use CODE128)" }, + }; + int data_size = ARRAY_SIZE(data); + + char escaped[1024]; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + symbol->debug = ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt + + int length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1 /*option_2*/, -1, data[i].output_options, data[i].data, -1, debug); + + ret = ZBarcode_Encode(symbol, data[i].data, length); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (generate) { + printf(" /*%3d*/ { %s, %s, %d, \"%s\", %s, %d, %d, \"%s\", \"%s\" },\n", + i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), data[i].output_options, + testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, symbol->errtxt, data[i].comment); + } else { + if (ret < 5) { + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); + assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + } + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_input(int index, int generate, int debug) { + + testStart(""); + + int ret; + struct item { + int input_mode; + unsigned char *data; + int length; + int ret; + int expected_width; + char *expected; + char *comment; + }; + // NUL U+0000, CodeA-only + // US U+001F (\037, 31), CodeA-only + // a U+0061 (\141, 97), CodeB-only + // b U+0062 (\142, 98), CodeB-only + // PAD U+0080 (\200, 128), UTF-8 C280 (\302\200), CodeA-only extended ASCII, not in ISO 8859-1 + // APC U+009F (\237, 159), UTF-8 C29F, CodeA-only extended ASCII, not in ISO 8859-1 + // ß U+00DF (\337, 223), UTF-8 C39F, CodeA and CodeB extended ASCII + // é U+00E9 (\351, 233), UTF-8 C3A9, CodeB-only extended ASCII + struct item data[] = { + /* 0*/ { UNICODE_MODE, "\302\200", -1, ZINT_ERROR_INVALID_DATA, 0, "Error 204: Invalid characters in input data", "PAD not in ISO 8859-1" }, + /* 1*/ { DATA_MODE, "\200", -1, 0, 57, "(5) 103 101 64 23 106", "PAD ok using binary" }, + /* 2*/ { UNICODE_MODE, "AIM1234", -1, 0, 101, "(9) 104 33 41 45 99 12 34 87 106", "Example from Annex A.1, check char value 87" }, + /* 3*/ { GS1_MODE, "[90]12", -1, ZINT_ERROR_INVALID_OPTION, 0, "Error 220: Selected symbology does not support GS1 mode", "" }, + /* 4*/ { UNICODE_MODE, "1", -1, 0, 46, "(4) 104 17 18 106", "StartB 1" }, + /* 5*/ { UNICODE_MODE, "12", -1, 0, 46, "(4) 105 12 14 106", "StartC 12" }, + /* 6*/ { UNICODE_MODE, "123", -1, 0, 68, "(6) 104 17 18 19 8 106", "StartB 1 2 3" }, + /* 7*/ { UNICODE_MODE, "1234", -1, 0, 57, "(5) 105 12 34 82 106", "StartC 12 34" }, + /* 8*/ { UNICODE_MODE, "12345", -1, 0, 79, "(7) 105 12 34 100 21 54 106", "StartC 12 34 CodeB 5" }, + /* 9*/ { UNICODE_MODE, "\037", -1, 0, 46, "(4) 103 95 95 106", "StartA US" }, + /* 10*/ { UNICODE_MODE, "1\037", -1, 0, 57, "(5) 103 17 95 1 106", "StartA 1 US" }, + /* 11*/ { UNICODE_MODE, "12\037", -1, 0, 68, "(6) 103 17 18 95 29 106", "StartA 1 2 US" }, + /* 12*/ { UNICODE_MODE, "a\037a", -1, 0, 79, "(7) 104 65 98 95 65 86 106", "StartB a Shift US a" }, + /* 13*/ { UNICODE_MODE, "1234\037a", -1, 0, 101, "(9) 105 12 34 101 95 98 65 100 106", "StartC 12 34 CodeA US Shift a" }, + /* 14*/ { UNICODE_MODE, "\037AAa\037", -1, 0, 101, "(9) 103 95 33 33 98 65 95 2 106", "StartA US A A Shift a US" }, + /* 15*/ { UNICODE_MODE, "\037AAaa\037", -1, 0, 123, "(11) 103 95 33 33 100 65 65 98 95 40 106", "StartA US A A CodeB a a Shift US" }, + /* 16*/ { UNICODE_MODE, "AAAa12345aAA", -1, 0, 167, "(15) 104 33 33 33 65 17 99 23 45 100 65 33 33 54 106", "StartB A (3) a 1 CodeC 23 45 CodeB a A A" }, + /* 17*/ { UNICODE_MODE, "a\037Aa\037\037a\037aa\037a", -1, 0, 222, "(20) 104 65 98 95 33 65 101 95 95 98 65 95 100 65 65 98 95 65 96 106", "StartB a Shift US A a CodeA US US Shift a US CodeB a a Shift US a" }, + /* 18*/ { UNICODE_MODE, "\000\037ß", 4, 0, 79, "(7) 103 64 95 101 63 88 106", "StartA NUL US FNC4 ß" }, + /* 19*/ { UNICODE_MODE, "\000\037é", 4, 0, 90, "(8) 103 64 95 101 98 73 78 106", "StartA NUL US FNC4 Shift é" }, + /* 20*/ { UNICODE_MODE, "\000\037éa", 5, 0, 101, "(9) 103 64 95 100 100 73 65 61 106", "StartA NUL US LatchB FNC4 é a" }, + /* 21*/ { UNICODE_MODE, "abß", -1, 0, 79, "(7) 104 65 66 100 63 29 106", "StartB a b FNC4 ß" }, + /* 22*/ { DATA_MODE, "\141\142\237", -1, 0, 90, "(8) 104 65 66 100 98 95 26 106", "StartB a b FNC4 Shift APC" }, + /* 23*/ { DATA_MODE, "\141\142\237\037", -1, 0, 101, "(9) 104 65 66 101 101 95 95 96 106", "StartB a b LatchA FNC4 APC US" }, + /* 24*/ { UNICODE_MODE, "ééé", -1, 0, 90, "(8) 104 100 100 73 73 73 44 106", "StartB LatchFNC4 é é é" }, + /* 25*/ { UNICODE_MODE, "aééééb", -1, 0, 145, "(13) 104 65 100 73 100 73 100 73 100 73 66 49 106", "StartB a FNC4 é (4) b" }, + /* 26*/ { UNICODE_MODE, "aéééééb", -1, 0, 145, "(13) 104 65 100 100 73 73 73 73 73 100 66 93 106", "StartB a Latch é (5) Shift b" }, + /* 27*/ { UNICODE_MODE, "aééééébc", -1, 0, 167, "(15) 104 65 100 100 73 73 73 73 73 100 66 100 67 40 106", "StartB a Latch é (5) Shift b Shift c" }, + /* 28*/ { UNICODE_MODE, "aééééébcd", -1, 0, 178, "(16) 104 65 100 100 73 73 73 73 73 100 100 66 67 68 66 106", "StartB a Latch é (5) Unlatch b c d" }, + /* 29*/ { UNICODE_MODE, "aééééébcde", -1, 0, 189, "(17) 104 65 100 100 73 73 73 73 73 100 100 66 67 68 69 2 106", "StartB a Latch é (5) Unlatch b c d e" }, + /* 30*/ { UNICODE_MODE, "aééééébcdeé", -1, 0, 211, "(19) 104 65 100 100 73 73 73 73 73 100 100 66 67 68 69 100 73 95 106", "StartB a Latch é (5) Unlatch b c d e FNC4 é" }, + /* 31*/ { UNICODE_MODE, "aééééébcdeéé", -1, 0, 233, "(21) 104 65 100 100 73 73 73 73 73 100 100 66 67 68 69 100 73 100 73 19 106", "StartB a Latch é (5) Unlatch b c d e FNC4 é (2)" }, + /* 32*/ { UNICODE_MODE, "aééééébcdeééé", -1, 0, 244, "(22) 104 65 100 100 73 73 73 73 73 100 66 100 67 100 68 100 69 73 73 73 83 106", "StartB a Latch é (5) Shift b Shift c Shift d Shift e é (3)" }, + /* 33*/ { UNICODE_MODE, "aééééébcdefééé", -1, 0, 255, "(23) 104 65 100 100 73 73 73 73 73 100 100 66 67 68 69 70 100 100 73 73 73 67 106", "StartB a Latch é (5) Unlatch b c d e f Latch é (3)" }, }; int data_size = sizeof(data) / sizeof(struct item); @@ -65,15 +278,24 @@ static void test_input(int index, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - symbol->symbology = data[i].symbology; - symbol->input_mode = data[i].input_mode; - symbol->debug |= debug; + symbol->debug = ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; + int length = testUtilSetSymbol(symbol, BARCODE_CODE128, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); ret = ZBarcode_Encode(symbol, data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + if (generate) { + printf(" /*%3d*/ { %s, \"%s\", %d, %s, %d, \"%s\", \"%s\" },\n", + i, testUtilInputModeName(data[i].input_mode), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].length, + testUtilErrorName(data[i].ret), symbol->width, symbol->errtxt, data[i].comment); + } else { + if (ret < 5) { + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); + assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + } + } + ZBarcode_Delete(symbol); } @@ -88,7 +310,6 @@ static void test_encode(int index, int generate, int debug) { struct item { int symbology; int input_mode; - int output_options; unsigned char *data; int ret; @@ -97,22 +318,83 @@ static void test_encode(int index, int generate, int debug) { char *comment; char *expected; }; + // BARCODE_EAN128 examples verified manually against GS1 General Specifications 20.0 struct item data[] = { - /* 0*/ { BARCODE_CODE128, UNICODE_MODE, -1, "AIM", 0, 1, 68, "ISO/IEC 15417:2007 Figure 1", + /* 0*/ { BARCODE_CODE128, UNICODE_MODE, "AIM", 0, 1, 68, "ISO/IEC 15417:2007 Figure 1", "11010010000101000110001100010001010111011000101110110001100011101011" - }, - /* 1*/ { BARCODE_CODE128B, UNICODE_MODE, -1, "AIM", 0, 1, 68, "128B same", + }, + /* 1*/ { BARCODE_CODE128B, UNICODE_MODE, "AIM", 0, 1, 68, "128B same", "11010010000101000110001100010001010111011000101110110001100011101011" - }, - /* 2*/ { BARCODE_CODE128, UNICODE_MODE, 16, "AIM", 0, 1, 79, "READER_INIT", - "1101001000010111100010101000110001100010001010111011000111010110001100011101011" - }, - /* 3*/ { BARCODE_CODE128, UNICODE_MODE, -1, "1234567890", 0, 1, 90, "", + }, + /* 2*/ { BARCODE_CODE128, UNICODE_MODE, "1234567890", 0, 1, 90, "", "110100111001011001110010001011000111000101101100001010011011110110100111100101100011101011" - }, - /* 4*/ { BARCODE_CODE128B, UNICODE_MODE, -1, "1234567890", 0, 1, 145, "", + }, + /* 3*/ { BARCODE_CODE128B, UNICODE_MODE, "1234567890", 0, 1, 145, "", "1101001000010011100110110011100101100101110011001001110110111001001100111010011101101110111010011001110010110010011101100101000110001100011101011" - }, + }, + /* 4*/ { BARCODE_EAN128, GS1_MODE, "[8018]950110153123456781", 0, 1, 167, "GS1 General Specifications Figure 2.5.2-1", + "11010011100111101011101010011110011001110010101111010001100110110011001000100101110011001101100011011101101110101110110001000010110010010111100101111001001100011101011" + }, + /* 5*/ { BARCODE_EAN128, GS1_MODE, "[415]5412345678908[3911]710125", 0, 1, 189, "GS1 General Specifications Figure 2.6.6-1 top", + "110100111001111010111011000100010111010001101100010001011101101110101110110001000010110011011011110100011001001101000100011000100100100110100001100110110011100101100100001001101100011101011" + }, + /* 6*/ { BARCODE_EAN128, GS1_MODE, "[12]010425[8020]ABC123", 0, 1, 189, "GS1 General Specifications Figure 2.6.6-1 bottom", + "110100111001111010111010110011100110011011001001000110011100101100101001111001100100111010111101110101000110001000101100010001000110100111001101100111001011001011100110010111001100011101011" + }, + /* 7*/ { BARCODE_EAN128, GS1_MODE, "[253]950110153005812345678901", 0, 1, 211, "GS1 General Specifications Figure 2.6.9-1", + "1101001110011110101110111001011001101000100011000101110110001001001100110110011011101110110110011001110110001010110011100100010110001110001011011000010100110111101101011110111010011100110101110110001100011101011" + }, + /* 8*/ { BARCODE_EAN128, GS1_MODE, "[253]950110153006567890543210987", 0, 1, 211, "GS1 General Specifications Figure 2.6.9-2", + "1101001110011110101110111001011001101000100011000101110110001001001100110110011011101110110110011001001011000010000101100110110111101000100110010110001110110111001001100100100011110010100101110011001100011101011" + }, + /* 9*/ { BARCODE_EAN128, GS1_MODE, "[253]95011015300657654321", 0, 1, 189, "GS1 General Specifications Figure 2.6.9-3", + "110100111001111010111011100101100110100010001100010111011000100100110011011001101110111011011001100100101100001100101000011101011000110001101101011110111010011100110111001001101100011101011" + }, + /* 10*/ { BARCODE_EAN128, GS1_MODE, "[253]9501101530065123456", 0, 1, 167, "GS1 General Specifications Figure 2.6.9-4", + "11010011100111101011101110010110011010001000110001011101100010010011001101100110111011101101100110010010110000101100111001000101100011100010110100011110101100011101011" + }, + /* 11*/ { BARCODE_EAN128, GS1_MODE, "[01]10857674002017[10]1152KMB", 0, 1, 211, "GS1 General Specifications Figure 4.15.1-1", + "1101001110011110101110110011011001100100010010011110010110010100001000011001011011001100110010011101001110011011001000100110001001001101110001010111101110101100011101011101100010001011000100111001101100011101011" + }, + /* 12*/ { BARCODE_EAN128, GS1_MODE, "[01]09501101530003", 0, 1, 134, "GS1 General Specifications Figure 5.1-3", + "11010011100111101011101100110110011001001000110001011101100010010011001101100110111011101101100110010010011000100110100001100011101011" + }, + /* 13*/ { BARCODE_EAN128, GS1_MODE, "[00]395123451234567895", 0, 1, 156, "GS1 General Specifications Figure 5.4.2-1", + "110100111001111010111011011001100110100010001101110100011101101110101110110001011001110010001011000111000101101100001010010111101000101111000101100011101011" + }, + /* 14*/ { BARCODE_EAN128, GS1_MODE, "[00]395011010013000129", 0, 1, 156, "GS1 General Specifications Figure 6.6.5-6", + "110100111001111010111011011001100110100010001100010111011000100100110011011001101100110010011011100110110011001100110110011100110010111101101101100011101011" + }, + /* 15*/ { BARCODE_EAN128, GS1_MODE, "[401]931234518430GR", 0, 1, 167, "GS1 General Specifications Figure 6.6.5-7 top", + "11010011100111101011101100010100011001011100110110001101110110111010111011000110011100101011000111010111101110100111011001101000100011000101110100110111001100011101011" + }, + /* 16*/ { BARCODE_EAN128, GS1_MODE, "[00]093123450000000012", 0, 1, 156, "GS1 General Specifications Figure 6.6.5-7 bottom", + "110100111001111010111011011001100110010010001101100011011101101110101110110001101100110011011001100110110011001101100110010110011100110111010001100011101011" + }, + /* 17*/ { BARCODE_EAN128, GS1_MODE, "[01]95012345678903", 0, 1, 134, "GS1 General Specifications Figure 7.8.5.1-1 1st", + "11010011100111101011101100110110010111101000110011011001110110111010111011000100001011001101101111010010011000110110001101100011101011" + }, + /* 18*/ { BARCODE_EAN128, GS1_MODE, "[3102]000400", 0, 1, 101, "GS1 General Specifications Figure 7.8.5.1-1 2nd", + "11010011100111101011101101100011011001100110110110011001001000110011011001100110110111101100011101011" + }, + /* 19*/ { BARCODE_EAN128, GS1_MODE, "[01]95012345678903[3102]000400", 0, 1, 189, "GS1 General Specifications Figure 7.8.5.1-2", + "110100111001111010111011001101100101111010001100110110011101101110101110110001000010110011011011110100100110001101100011011001100110110110011001001000110011011001100100100110001100011101011" + }, + /* 20*/ { BARCODE_EAN128, GS1_MODE, "[8005]000365", 0, 1, 101, "GS1 General Specifications Figure 7.8.5.2-1 1st", + "11010011100111101011101010011110010001001100110110011001001001100010010110000100100001101100011101011" + }, + /* 21*/ { BARCODE_EAN128, GS1_MODE, "[10]123456", 0, 1, 90, "GS1 General Specifications Figure 7.8.5.2-1 2nd", + "110100111001111010111011001000100101100111001000101100011100010110110010000101100011101011" + }, + /* 22*/ { BARCODE_EAN128, GS1_MODE, "[8005]000365[10]123456", 0, 1, 156, "GS1 General Specifications Figure 7.8.5.2-2", + "110100111001111010111010100111100100010011001101100110010010011000100101100001111010111011001000100101100111001000101100011100010110101100001001100011101011" + }, + /* 23*/ { BARCODE_EAN14, GS1_MODE, "4070071967072", 0, 1, 134, "Verified manually against bwipp and tec-it", + "11010011100111101011101100110110011000101000101100001001001100010011001011100100001011001001100010011001001110110111001001100011101011" + }, + /* 24*/ { BARCODE_NVE18, GS1_MODE, "40700000071967072", 0, 1, 156, "Verified manually against bwipp (sscc18) and tec-it", + "110100111001111010111011011001100110001010001011000010011011001100110110011001001100010011001011100100001011001001100010011001001110110111011101100011101011" + }, }; int data_size = sizeof(data) / sizeof(struct item); @@ -125,24 +407,17 @@ static void test_encode(int index, int generate, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - symbol->symbology = data[i].symbology; - symbol->input_mode = data[i].input_mode; - if (data[i].output_options != -1) { - symbol->output_options = data[i].output_options; - } - symbol->debug |= debug; - - int length = strlen(data[i].data); + int length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %s, %s, %d, \"%s\", %s, %d, %d, \"%s\",\n", - i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), data[i].output_options, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), + printf(" /*%3d*/ { %s, %s, \"%s\", %s, %d, %d, \"%s\",\n", + i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment); testUtilModulesDump(symbol, " ", "\n"); - printf(" },\n"); + printf(" },\n"); } else { if (ret < 5) { assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); @@ -165,7 +440,10 @@ static void test_encode(int index, int generate, int debug) { int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ - { "test_input", test_input, 1, 0, 1 }, + { "test_large", test_large, 1, 0, 1 }, + { "test_hrt", test_hrt, 1, 0, 1 }, + { "test_reader_init", test_reader_init, 1, 1, 1 }, + { "test_input", test_input, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 }, }; diff --git a/backend/tests/test_gs1.c b/backend/tests/test_gs1.c index c6988599..82d794a8 100644 --- a/backend/tests/test_gs1.c +++ b/backend/tests/test_gs1.c @@ -51,7 +51,7 @@ static void test_gs1_reduce(int index, int generate, int debug) { }; struct item data[] = { /* 0*/ { BARCODE_EAN128, -1, "12345678901234", "", ZINT_ERROR_INVALID_DATA, "GS1 data required", "" }, - /* 1*/ { BARCODE_EAN128, -1, "[01]12345678901234", "", 0, "Input mode ignored", + /* 1*/ { BARCODE_EAN128, -1, "[01]12345678901234", "", 0, "Input mode ignored; verified manually against bwipp and tec-it", "11010011100111101011101100110110010110011100100010110001110001011011000010100110111101101011001110010001011000111010111101100011101011" }, /* 2*/ { BARCODE_EAN128, GS1_MODE, "[01]12345678901234", "", 0, "Input mode ignored", @@ -81,7 +81,7 @@ static void test_gs1_reduce(int index, int generate, int debug) { "0010110001100001010001001100100110100110001101110100111000111010010011110101100100001001010011000110111010011100010100001011010000110011100010100" "1101001110011110101110110011011001011001110010001011000111000101101100001010011011110110101100111001000101100011101011110100101111001100011101011" }, - /* 7*/ { BARCODE_EAN14, -1, "1234567890123", "", 0, "Input mode ignored", + /* 7*/ { BARCODE_EAN14, -1, "1234567890123", "", 0, "Input mode ignored; verified manually against bwipp and tec-it", "11010011100111101011101100110110010110011100100010110001110001011011000010100110111101101011001110011011000110100001100101100011101011" }, /* 8*/ { BARCODE_EAN14, GS1_MODE, "1234567890123", "", 0, "Input mode ignored", @@ -90,7 +90,7 @@ static void test_gs1_reduce(int index, int generate, int debug) { /* 9*/ { BARCODE_EAN14, UNICODE_MODE, "1234567890123", "", 0, "Input mode ignored", "11010011100111101011101100110110010110011100100010110001110001011011000010100110111101101011001110011011000110100001100101100011101011" }, - /*10*/ { BARCODE_NVE18, -1, "12345678901234567", "", 0, "Input mode ignored", + /*10*/ { BARCODE_NVE18, -1, "12345678901234567", "", 0, "Input mode ignored; verified manually against bwipp (sscc18) and tec-it", "110100111001111010111011011001100101100111001000101100011100010110110000101001101111011010110011100100010110001110001011011000010010101101110001100011101011" }, /*11*/ { BARCODE_NVE18, GS1_MODE, "12345678901234567", "", 0, "Input mode ignored", @@ -228,12 +228,16 @@ static void test_hrt(int index, int debug) { unsigned char *expected; }; - // s/\/\*[ 0-9]*\*\//\=printf("\/*%2d*\/", line(".") - line("'<")) + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { - /* 0*/ { BARCODE_EAN128, "[01]12345678901234[20]12", "", "(01)12345678901234(20)12" }, - /* 1*/ { BARCODE_EAN128_CC, "[01]12345678901234[20]12", "[21]12345", "(01)12345678901234(20)12" }, - /* 2*/ { BARCODE_RSS_EXP, "[01]12345678901234[20]12", "", "(01)12345678901234(20)12" }, - /* 3*/ { BARCODE_RSS_EXP_CC, "[01]12345678901234", "[21]12345", "(01)12345678901234" }, + /* 0*/ { BARCODE_EAN128, "[01]12345678901234[20]12", "", "(01)12345678901234(20)12" }, + /* 1*/ { BARCODE_EAN128_CC, "[01]12345678901234[20]12", "[21]12345", "(01)12345678901234(20)12" }, + /* 2*/ { BARCODE_EAN14, "1234567890123", "", "(01)12345678901231" }, + /* 3*/ { BARCODE_NVE18, "12345678901234567", "", "(00)123456789012345675" }, + /* 4*/ { BARCODE_RSS_EXP, "[01]12345678901234[20]12", "", "(01)12345678901234(20)12" }, + /* 5*/ { BARCODE_RSS_EXP_CC, "[01]12345678901234", "[21]12345", "(01)12345678901234" }, + /* 6*/ { BARCODE_RSS_EXPSTACK, "[01]12345678901234[20]12", "", "" }, + /* 7*/ { BARCODE_RSS_EXPSTACK_CC, "[01]12345678901234[20]12", "[21]12345", "" }, }; int data_size = sizeof(data) / sizeof(struct item); diff --git a/backend/tests/test_library.c b/backend/tests/test_library.c index de539112..d2331543 100644 --- a/backend/tests/test_library.c +++ b/backend/tests/test_library.c @@ -153,6 +153,60 @@ static void test_input_mode(int index, int debug) { testFinish(); } +static void test_escape_char_process(int index, int generate, int debug) { + + testStart(""); + + int ret; + struct item { + unsigned char *data; + int ret; + int expected_width; + char *expected; + char *comment; + }; + struct item data[] = { + /* 0*/ { "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\e\\G\\R\\x81\\\\", 0, 200, "(18) 103 64 68 71 72 73 74 75 76 77 91 93 94 101 65 60 44 106", "" }, + /* 1*/ { "\\c", ZINT_ERROR_INVALID_DATA, 0, "Error 234: Unrecognised escape character in input data", "" }, + /* 2*/ { "\\", ZINT_ERROR_INVALID_DATA, 0, "Error 236: Incomplete escape character in input data", "" }, + /* 3*/ { "\\x", ZINT_ERROR_INVALID_DATA, 0, "Error 232: Incomplete escape character in input data", "" }, + /* 4*/ { "\\x1", ZINT_ERROR_INVALID_DATA, 0, "Error 232: Incomplete escape character in input data", "" }, + /* 5*/ { "\\x1g", ZINT_ERROR_INVALID_DATA, 0, "Error 233: Corrupt escape character in input data", "" }, + }; + int data_size = ARRAY_SIZE(data); + + char escaped[1024]; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + symbol->debug = ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt + + int length = testUtilSetSymbol(symbol, BARCODE_CODE128, DATA_MODE | ESCAPE_MODE, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); + + ret = ZBarcode_Encode(symbol, data[i].data, length); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (generate) { + printf(" /*%3d*/ { \"%s\", %s, %d, \"%s\", \"%s\" },\n", + i, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), testUtilErrorName(data[i].ret), symbol->width, symbol->errtxt, data[i].comment); + } else { + if (ret < 5) { + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); + assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + } + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + // #181 Nico Gunkel OSS-Fuzz static void test_encode_file_zero_length(void) { @@ -210,6 +264,7 @@ int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ { "test_checks", test_checks, 1, 0, 1 }, { "test_input_mode", test_input_mode, 1, 0, 1 }, + { "test_escape_char_process", test_escape_char_process, 1, 1, 1 }, { "test_encode_file_zero_length", test_encode_file_zero_length, 0, 0, 0 }, { "test_encode_file_directory", test_encode_file_directory, 0, 0, 0 }, }; diff --git a/backend/tests/test_raster.c b/backend/tests/test_raster.c index d119d37e..be6cca2e 100644 --- a/backend/tests/test_raster.c +++ b/backend/tests/test_raster.c @@ -31,6 +31,11 @@ #include "testcommon.h" +static int is_row_column_black(struct zint_symbol *symbol, int row, int column) { + int i = (row * symbol->bitmap_width + column) * 3; + return symbol->bitmap[i] == 0 && symbol->bitmap[i + 1] == 0 && symbol->bitmap[i + 2] == 0; // Black +} + static void test_chk_extendable(int index, int debug) { testStart(""); @@ -87,8 +92,7 @@ static void test_chk_extendable(int index, int debug) { int addon_text_bits_set = 0; int row = data[i].expected_addon_text_row; for (int column = data[i].expected_addon_text_col; column < data[i].expected_addon_text_col + 48; column++) { - int j = (row * symbol->bitmap_width + column) * 3; - if (symbol->bitmap[j] == 0 && symbol->bitmap[j + 1] == 0 && symbol->bitmap[j + 2] == 0) { // Black + if (is_row_column_black(symbol, row, column)) { addon_text_bits_set = 1; break; } @@ -105,10 +109,83 @@ static void test_chk_extendable(int index, int debug) { testFinish(); } +static void test_row_separator(int index, int debug) { + + testStart(""); + + int ret; + struct item { + int symbology; + int option_3; + unsigned char *data; + int ret; + + int expected_height; + int expected_rows; + int expected_width; + int expected_bitmap_width; + int expected_bitmap_height; + int expected_separator_row; + int expected_separator_col; + int expected_separator_height; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { BARCODE_CODABLOCKF, -1, "A", 0, 20, 2, 101, 210, 48, 22, 28, 4 }, // Col 28 TODO: investigate extra 2 compared to vector 26 + /* 1*/ { BARCODE_CODABLOCKF, 0, "A", 0, 20, 2, 101, 210, 48, 22, 28, 4 }, // Same as default + /* 2*/ { BARCODE_CODABLOCKF, 1, "A", 0, 20, 2, 101, 210, 48, 23, 28, 2 }, + /* 3*/ { BARCODE_CODABLOCKF, 2, "A", 0, 20, 2, 101, 210, 48, 22, 28, 4 }, // Same as default + /* 4*/ { BARCODE_CODABLOCKF, 3, "A", 0, 20, 2, 101, 210, 48, 21, 28, 6 }, + /* 5*/ { BARCODE_CODABLOCKF, 4, "A", 0, 20, 2, 101, 210, 48, 20, 28, 8 }, + /* 6*/ { BARCODE_CODABLOCKF, 5, "A", 0, 20, 2, 101, 210, 48, 22, 28, 4 }, // > 4 ignored, same as default + }; + int data_size = ARRAY_SIZE(data); + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + int length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, data[i].option_3, -1 /*output_options*/, data[i].data, -1, debug); + + ret = ZBarcode_Encode_and_Buffer(symbol, data[i].data, length, 0); + assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret); + assert_nonnull(symbol->bitmap, "i:%d (%d) symbol->bitmap NULL\n", i, data[i].symbology); + + assert_equal(symbol->height, data[i].expected_height, "i:%d (%d) symbol->height %d != %d\n", i, data[i].symbology, symbol->height, data[i].expected_height); + assert_equal(symbol->rows, data[i].expected_rows, "i:%d (%d) symbol->rows %d != %d\n", i, data[i].symbology, symbol->rows, data[i].expected_rows); + assert_equal(symbol->width, data[i].expected_width, "i:%d (%d) symbol->width %d != %d\n", i, data[i].symbology, symbol->width, data[i].expected_width); + assert_equal(symbol->bitmap_width, data[i].expected_bitmap_width, "i:%d (%d) symbol->bitmap_width %d != %d\n", i, data[i].symbology, symbol->bitmap_width, data[i].expected_bitmap_width); + assert_equal(symbol->bitmap_height, data[i].expected_bitmap_height, "i:%d (%d) symbol->bitmap_height %d != %d\n", i, data[i].symbology, symbol->bitmap_height, data[i].expected_bitmap_height); + + int j, separator_bits_set; + + for (j = data[i].expected_separator_row; j < data[i].expected_separator_row + data[i].expected_separator_height; j++) { + separator_bits_set = is_row_column_black(symbol, j, data[i].expected_separator_col); + assert_nonzero(separator_bits_set, "i:%d (%d) separator_bits_set (%d, %d) zero\n", i, data[i].symbology, j, data[i].expected_separator_col); + } + + j = data[i].expected_separator_row - 1; + separator_bits_set = is_row_column_black(symbol, j, data[i].expected_separator_col); + assert_zero(separator_bits_set, "i:%d (%d) separator_bits_set (%d, %d) before non-zero\n", i, data[i].symbology, j, data[i].expected_separator_col); + + j = data[i].expected_separator_row + data[i].expected_separator_height; + separator_bits_set = is_row_column_black(symbol, j, data[i].expected_separator_col); + assert_zero(separator_bits_set, "i:%d (%d) separator_bits_set (%d, %d) after non-zero\n", i, data[i].symbology, j, data[i].expected_separator_col); + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ { "test_chk_extendable", test_chk_extendable, 1, 0, 1 }, + { "test_row_separator", test_row_separator, 1, 0, 1 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/test_vector.c b/backend/tests/test_vector.c index 5659caab..ef0b2fd5 100644 --- a/backend/tests/test_vector.c +++ b/backend/tests/test_vector.c @@ -31,6 +31,35 @@ #include "testcommon.h" +static struct zint_vector_rect *find_rect(struct zint_symbol *symbol, int x, int y, int height, int width) { + struct zint_vector_rect *rect; + + if (symbol->vector == NULL) { + return NULL; + } + for (rect = symbol->vector->rectangles; rect != NULL; rect = rect->next) { + if (rect->x == x && rect->y == y) { + if (height && width) { + if (rect->height == height && rect->width == width) { + break; + } + } else if (height) { + if (rect->height == height) { + break; + } + } else if (width) { + if (rect->width == width) { + break; + } + } else { + break; + } + } + } + + return rect; +} + static void test_buffer_vector(int index, int generate, int debug) { testStart(""); @@ -96,7 +125,7 @@ static void test_buffer_vector(int index, int generate, int debug) { /* 45*/ { BARCODE_DATAMATRIX, "ABC", "", 10, 10, 10, 20.0, 20.0 }, /* 46*/ { BARCODE_EAN14, "1234567890123", "", 50, 1, 134, 268.0, 118.0 }, /* 47*/ { BARCODE_VIN, "00000000000000000", "", 50, 1, 246, 492.0, 118.0 }, - /* 48*/ { BARCODE_CODABLOCKF, "0000000000", "", 10, 1, 90, 188.0, 28.0 }, + /* 48*/ { BARCODE_CODABLOCKF, "0000000000", "", 20, 2, 101, 210.0, 48.0 }, /* 49*/ { BARCODE_NVE18, "12345678901234567", "", 50, 1, 156, 312.0, 118.0 }, /* 50*/ { BARCODE_JAPANPOST, "0000000000", "", 8, 3, 133, 266.0, 16.0 }, /* 51*/ { BARCODE_KOREAPOST, "123456", "", 50, 1, 167, 334.0, 118.0 }, @@ -119,7 +148,7 @@ static void test_buffer_vector(int index, int generate, int debug) { /* 68*/ { BARCODE_HIBC_QR, "1234567890AB", "", 21, 21, 21, 42.0, 42.0 }, /* 69*/ { BARCODE_HIBC_PDF, "0000000000", "", 27, 9, 103, 206.0, 54.0 }, /* 70*/ { BARCODE_HIBC_MICPDF, "0000000000", "", 34, 17, 38, 76.0, 68.0 }, - /* 71*/ { BARCODE_HIBC_BLOCKF, "0000000000", "", 40, 4, 90, 188.0, 88.0 }, + /* 71*/ { BARCODE_HIBC_BLOCKF, "0000000000", "", 30, 3, 101, 210.0, 68.0 }, /* 72*/ { BARCODE_HIBC_AZTEC, "1234567890AB", "", 19, 19, 19, 38.0, 38.0 }, /* 73*/ { BARCODE_DOTCODE, "ABC", "", 11, 11, 16, 32.0, 22.0 }, /* 74*/ { BARCODE_HANXIN, "1234567890AB", "", 23, 23, 23, 46.0, 46.0 }, @@ -311,12 +340,74 @@ static void test_upcean_whitespace_width(int index, int debug) { testFinish(); } +static void test_row_separator(int index, int debug) { + + testStart(""); + + int ret; + struct item { + int symbology; + int option_3; + unsigned char *data; + int ret; + + int expected_height; + int expected_rows; + int expected_width; + int expected_separator_row; + int expected_separator_col; + int expected_separator_height; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { BARCODE_CODABLOCKF, -1, "A", 0, 20, 2, 101, 22, 26, 4 }, + /* 1*/ { BARCODE_CODABLOCKF, 0, "A", 0, 20, 2, 101, 22, 26, 4 }, // Same as default + /* 2*/ { BARCODE_CODABLOCKF, 1, "A", 0, 20, 2, 101, 23, 26, 2 }, + /* 3*/ { BARCODE_CODABLOCKF, 2, "A", 0, 20, 2, 101, 22, 26, 4 }, // Same as default + /* 4*/ { BARCODE_CODABLOCKF, 3, "A", 0, 20, 2, 101, 21, 26, 6 }, + /* 5*/ { BARCODE_CODABLOCKF, 4, "A", 0, 20, 2, 101, 20, 26, 8 }, + /* 6*/ { BARCODE_CODABLOCKF, 5, "A", 0, 20, 2, 101, 22, 26, 4 }, // > 4 ignored, same as default + }; + int data_size = ARRAY_SIZE(data); + + struct zint_vector_rect *rect; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + int length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, data[i].option_3, -1 /*output_options*/, data[i].data, -1, debug); + + ret = ZBarcode_Encode(symbol, data[i].data, length); + assert_zero(ret, "i:%d ZBarcode_Encode(%d) ret %d != 0 %s\n", i, data[i].symbology, ret, symbol->errtxt); + + ret = ZBarcode_Buffer_Vector(symbol, 0); + assert_zero(ret, "i:%d ZBarcode_Buffer_Vector(%d) ret %d != 0\n", i, data[i].symbology, ret); + assert_nonnull(symbol->vector, "i:%d ZBarcode_Buffer_Vector(%d) vector NULL\n", i, data[i].symbology); + + assert_equal(symbol->height, data[i].expected_height, "i:%d (%d) symbol->height %d != %d\n", i, data[i].symbology, symbol->height, data[i].expected_height); + assert_equal(symbol->rows, data[i].expected_rows, "i:%d (%d) symbol->rows %d != %d\n", i, data[i].symbology, symbol->rows, data[i].expected_rows); + assert_equal(symbol->width, data[i].expected_width, "i:%d (%d) symbol->width %d != %d\n", i, data[i].symbology, symbol->width, data[i].expected_width); + + rect = find_rect(symbol, data[i].expected_separator_col, data[i].expected_separator_row, data[i].expected_separator_height, 0); + assert_nonnull(rect, "i:%d (%d) find_rect(%d, %d, %d) NULL\n", i, data[i].symbology, data[i].expected_separator_col, data[i].expected_separator_row, data[i].expected_separator_height); + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ { "test_buffer_vector", test_buffer_vector, 1, 1, 1 }, { "test_noncomposite_string_x", test_noncomposite_string_x, 1, 0, 1 }, { "test_upcean_whitespace_width", test_upcean_whitespace_width, 1, 0, 1 }, + { "test_row_separator", test_row_separator, 1, 0, 1 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/testcommon.c b/backend/tests/testcommon.c index 4b92dbc3..daa96d13 100644 --- a/backend/tests/testcommon.c +++ b/backend/tests/testcommon.c @@ -389,6 +389,34 @@ char *testUtilBarcodeName(int symbology) { return data[symbology].name; } +int testUtilSetSymbol(struct zint_symbol *symbol, int symbology, int input_mode, int eci, int option_1, int option_2, int option_3, int output_options, char *data, int length, int debug) { + symbol->symbology = symbology; + if (input_mode != -1) { + symbol->input_mode = input_mode; + } + if (eci != -1) { + symbol->eci = eci; + } + if (option_1 != -1) { + symbol->option_1 = option_1; + } + if (option_2 != -1) { + symbol->option_2 = option_2; + } + if (option_3 != -1) { + symbol->option_3 = option_3; + } + if (output_options != -1) { + symbol->output_options = output_options; + } + symbol->debug |= debug; + if (length == -1) { + length = strlen(data); + } + + return length; +} + char *testUtilErrorName(int error_number) { struct item { int define; @@ -499,9 +527,9 @@ int testUtilIsValidUTF8(const unsigned char str[], const size_t length) { char *testUtilEscape(char *buffer, int length, char *escaped, int escaped_size) { int i; - unsigned char *b = buffer; - unsigned char *be = buffer + length; - int non_utf8 = !testUtilIsValidUTF8(buffer, length); + unsigned char *b = (unsigned char *) buffer; + unsigned char *be = b + length; + int non_utf8 = !testUtilIsValidUTF8(b, length); for (i = 0; b < be && i < escaped_size; b++) { if (non_utf8 || *b < ' ' || *b == '\177') { diff --git a/backend/tests/testcommon.h b/backend/tests/testcommon.h index 9243ef70..6d642dc2 100644 --- a/backend/tests/testcommon.h +++ b/backend/tests/testcommon.h @@ -72,6 +72,7 @@ void testRun(int argc, char *argv[], testFunction funcs[], int funcs_size); extern void vector_free(struct zint_symbol *symbol); /* Free vector structures */ +int testUtilSetSymbol(struct zint_symbol *symbol, int symbology, int input_mode, int eci, int option_1, int option_2, int option_3, int output_options, char *data, int length, int debug); char *testUtilBarcodeName(int symbology); char *testUtilErrorName(int error_number); char *testUtilInputModeName(int input_mode); diff --git a/backend/vector.c b/backend/vector.c index b9360be4..a341ae07 100644 --- a/backend/vector.c +++ b/backend/vector.c @@ -785,14 +785,19 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ // Binding and boxes if ((symbol->output_options & BARCODE_BIND) != 0) { if ((symbol->rows > 1) && (is_stackable(symbol->symbology) == 1)) { + double sep_height = 2; + + if (symbol->option_3 > 0 && symbol->option_3 <= 4) { + sep_height = symbol->option_3; + } /* row binding */ for (r = 1; r < symbol->rows; r++) { - if (symbol->symbology != BARCODE_CODABLOCKF) { - rectangle = vector_plot_create_rect((float)xoffset, (r * row_height) + yoffset - 1, (float)symbol->width, 2.0f); + if (symbol->symbology != BARCODE_CODABLOCKF && symbol->symbology != BARCODE_HIBC_BLOCKF) { + rectangle = vector_plot_create_rect((float)xoffset, (r * row_height) + yoffset - sep_height / 2, (float)symbol->width, sep_height); vector_plot_add_rect(symbol, rectangle, &last_rectangle); } else { /* Avoid 11-module start and stop chars */ - rectangle = vector_plot_create_rect(xoffset + 11, (r * row_height) + yoffset - 1, symbol->width - 22, 2.0); + rectangle = vector_plot_create_rect(xoffset + 11, (r * row_height) + yoffset - sep_height / 2, symbol->width - 22, sep_height); vector_plot_add_rect(symbol, rectangle, &last_rectangle); } } @@ -801,14 +806,14 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) { // Top rectangle = vector_plot_create_rect(0.0f, 0.0f, vector->width, (float)symbol->border_width); - if (symbol->symbology == BARCODE_CODABLOCKF) { + if (symbol->symbology == BARCODE_CODABLOCKF || symbol->symbology == BARCODE_HIBC_BLOCKF) { rectangle->x = (float)xoffset; rectangle->width -= (2.0f * xoffset); } vector_plot_add_rect(symbol, rectangle, &last_rectangle); // Bottom rectangle = vector_plot_create_rect(0.0f, vector->height - symbol->border_width - text_offset, vector->width, (float)symbol->border_width); - if (symbol->symbology == BARCODE_CODABLOCKF) { + if (symbol->symbology == BARCODE_CODABLOCKF || symbol->symbology == BARCODE_HIBC_BLOCKF) { rectangle->x = (float)xoffset; rectangle->width -= (2.0f * xoffset); } diff --git a/backend_qt/qzint.cpp b/backend_qt/qzint.cpp index 01b0cc9f..44fd40cf 100644 --- a/backend_qt/qzint.cpp +++ b/backend_qt/qzint.cpp @@ -14,6 +14,7 @@ * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ +/* vim: set ts=4 sw=4 et : */ #include "qzint.h" #include @@ -71,7 +72,7 @@ namespace Zint { } else { m_zintSymbol->show_hrt = 1; } - m_zintSymbol->option_3 = m_option_3; + m_zintSymbol->option_3 = m_option_3; QByteArray bstr = m_text.toUtf8(); QByteArray pstr = m_primaryMessage.left(99).toLatin1(); strcpy(m_zintSymbol->primary, pstr.data()); @@ -236,7 +237,7 @@ namespace Zint { } else { m_zintSymbol->show_hrt = 1; } - m_zintSymbol->option_3 = m_option_3; + m_zintSymbol->option_3 = m_option_3; m_zintSymbol->scale = m_scale; QByteArray bstr = m_text.toUtf8(); QByteArray pstr = m_primaryMessage.left(99).toLatin1(); @@ -263,6 +264,8 @@ namespace Zint { struct zint_vector_string *string; qreal radius; + (void)mode; /* Not currently used */ + encode(); QFont fontSmall(fontstyle); diff --git a/docs/manual.txt b/docs/manual.txt index 837dc887..4613d4cf 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -1545,18 +1545,25 @@ error = ZBarcode_Encode(my_symbol, "That"); error = ZBarcode_Print(my_symbol); +The stacked barcode rows can be separated by row separator bars by specifying +--bind (output_options |= BARCODE_BIND). The height of the row separator bars +in x-dimension multiples (default 2, minimum 1, maximum 4) can be set by +--separator= (option_3): + +zind --bind --separator=1 -d 'This' -d 'That' + A more sophisticated method is to use some type of line indexing which indicates to the barcode reader which order the symbols should be read. This is demonstrated by the symbologies below. 6.2.2 Codablock-F ----------------- -This is a stacked symbology based on Code 128 which can encode ASCII code set -data up to a maximum length of 2725 characters. The width of the Codablock-F -symbol can be set using the --cols= option at the command line or option_2. -Alternatively the height (number of rows) can be set using the --rows= option -at the command line or by setting option_1. Zint does not support encoding of -GS1 data in Codablock-F symbols. +This is a stacked symbology based on Code 128 which can encode extended ASCII +code set data up to a maximum length of 2725 characters. The width of the +Codablock-F symbol can be set using the --cols= option at the command line or +option_2. The height (number of rows) can be set using the --rows= option at the +command line or by setting option_1. Zint does not support encoding of GS1 data +in Codablock-F symbols. 6.2.3 Code 16k (EN 12323) ------------------------- diff --git a/frontend/main.c b/frontend/main.c index 5c07782a..151af61f 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +/* vim: set ts=4 sw=4 et : */ #include #include @@ -60,7 +61,7 @@ void types(void) { "30: GS1 DataBar Ltd 79: GS1 DataBar Stack 136: Comp UPC-E\n" "31: GS1 DataBar ExpOm 80: GS1 DataBar Stack Omni 137: Comp DataBar Stack\n" "32: Telepen Alpha 81: GS1 DataBar ESO 138: Comp DataBar Stack Omni\n" - "34: UPC-A 82: Planet 1139: Comp DataBar ESO\n" + "34: UPC-A 82: Planet 139: Comp DataBar ESO\n" "35: UPC-A + Check 84: MicroPDF 140: Channel Code\n" "37: UPC-E 85: USPS OneCode 141: Code One\n" "38: UPC-E + Check 86: UK Plessey 142: Grid Matrix\n" @@ -88,16 +89,16 @@ void usage(void) { " --cols=NUMBER Set the number of data columns in symbol\n" " -d, --data=DATA Set the symbol content\n" " --direct Send output to stdout\n" + " --dmre Allow Data Matrix Rectangular Extended\n" " --dotsize=NUMBER Set radius of dots in dotty mode\n" " --dotty Use dots instead of squares for matrix symbols\n" - " --dmre Allow Data Matrix Rectangular Extended\n" " --dump Dump hexadecimal representation to stdout\n" " -e, --ecinos Display table of ECI character encodings\n" " --eci=NUMBER Set the ECI mode for raw data\n" " --esc Process escape characters in input data\n" - " --filetype=TYPE Set output file type (PNG/EPS/SVG/PNG/EPS/GIF/TXT)\n" " --fg=COLOUR Specify a foreground colour (in hex)\n" - " --fullmultibyte Use multibyte mode for binary and Latin (QR Code/Han Xin/Grid Matrix)\n" + " --filetype=TYPE Set output file type (PNG/EPS/SVG/PNG/EPS/GIF/TXT)\n" + " --fullmultibyte Use multibyte for binary/Latin (QR/Han Xin/Grid Matrix)\n" " --gs1 Treat input as GS1 compatible data\n" " --gssep Use separator GS for GS1\n" " -h, --help Display help message\n" @@ -109,8 +110,9 @@ void usage(void) { " --notext Remove human readable text\n" " -o, --output=FILE Send output to FILE. (default is out.png)\n" " --primary=STRING Set structured primary message (Maxicode/Composite)\n" - " --secure=NUMBER Set error correction level\n" " --scale=NUMBER Adjust size of x-dimension\n" + " --secure=NUMBER Set error correction level\n" + " --separator=NUMBER Set height of row separator bars (stacked symbologies)\n" " --small Use half-size text in PNG images\n" " --square Force Data Matrix symbols to be square\n" " -r, --reverse Reverse colours (white on black)\n" @@ -380,17 +382,42 @@ int batch_process(struct zint_symbol *symbol, char *filename, int mirror_mode, c } int is_fullmultibyte(struct zint_symbol* symbol) { - switch (symbol->symbology) { - case BARCODE_QRCODE: - case BARCODE_MICROQR: - //case BARCODE_HIBC_QR: Note character set restricted to ASCII subset - //case BARCODE_UPNQR: Note does not use Kanji mode - case BARCODE_RMQR: - case BARCODE_HANXIN: - case BARCODE_GRIDMATRIX: - return 1; - } - return 0; + switch (symbol->symbology) { + case BARCODE_QRCODE: + case BARCODE_MICROQR: + //case BARCODE_HIBC_QR: Note character set restricted to ASCII subset + //case BARCODE_UPNQR: Note does not use Kanji mode + case BARCODE_RMQR: + case BARCODE_HANXIN: + case BARCODE_GRIDMATRIX: + return 1; + } + return 0; +} + +/* Indicates which symbologies can have row binding + * Note: if change this must also change version in backend/common.c */ +int is_stackable(const int symbology) { + if (symbology < BARCODE_PDF417) { + return 1; + } + + switch (symbology) { + case BARCODE_CODE128B: + case BARCODE_ISBNX: + case BARCODE_EAN14: + case BARCODE_NVE18: + case BARCODE_KOREAPOST: + case BARCODE_PLESSEY: + case BARCODE_TELEPEN_NUM: + case BARCODE_ITF14: + case BARCODE_CODE32: + case BARCODE_CODABLOCKF: + case BARCODE_HIBC_BLOCKF: + return 1; + } + + return 0; } int main(int argc, char **argv) { @@ -400,7 +427,8 @@ int main(int argc, char **argv) { int generated; int batch_mode; int mirror_mode; - int fullmultibyte; + int fullmultibyte; + int separator; char filetype[4]; int i; @@ -412,6 +440,7 @@ int main(int argc, char **argv) { batch_mode = 0; mirror_mode = 0; fullmultibyte = 0; + separator = 0; for (i = 0; i < 4; i++) { filetype[i] = '\0'; @@ -450,6 +479,7 @@ int main(int argc, char **argv) { {"mode", 1, 0, 0}, {"primary", 1, 0, 0}, {"scale", 1, 0, 0}, + {"separator", 1, 0, 0}, {"gs1", 0, 0, 0}, {"gssep", 0, 0, 0}, {"binary", 0, 0, 0}, @@ -547,6 +577,15 @@ int main(int argc, char **argv) { my_symbol->scale = 1.0; } } + if (!strcmp(long_options[option_index].name, "separator")) { + separator = atoi(optarg); + if (separator < 0 || separator > 4) { + /* Negative and greater than 4 values are not permitted */ + fprintf(stderr, "Warning 127: Invalid separator value\n"); + fflush(stderr); + separator = 0; + } + } if (!strcmp(long_options[option_index].name, "dotsize")) { my_symbol->dot_size = (float) (atof(optarg)); if (my_symbol->dot_size < 0.01) { @@ -584,7 +623,7 @@ int main(int argc, char **argv) { } if (!strcmp(long_options[option_index].name, "cols")) { - if ((atoi(optarg) >= 1) && (atoi(optarg) <= 66)) { + if ((atoi(optarg) >= 1) && (atoi(optarg) <= 67)) { my_symbol->option_2 = atoi(optarg); } else { fprintf(stderr, "Warning 111: Number of columns out of range\n"); @@ -681,7 +720,7 @@ int main(int argc, char **argv) { if ((atoi(optarg) >= 0) && (atoi(optarg) <= 100)) { my_symbol->fontsize = atoi(optarg); } else { - fprintf(stderr, "Warning 125: Invalid font size\n"); + fprintf(stderr, "Warning 126: Invalid font size\n"); fflush(stderr); } } @@ -728,9 +767,11 @@ int main(int argc, char **argv) { strcat(my_symbol->outfile, "."); strcat(my_symbol->outfile, filetype); } - if (fullmultibyte && is_fullmultibyte(my_symbol)) { - my_symbol->option_3 = ZINT_FULL_MULTIBYTE; - } + if (fullmultibyte && is_fullmultibyte(my_symbol)) { + my_symbol->option_3 = ZINT_FULL_MULTIBYTE; + } else if (separator && is_stackable(my_symbol->symbology)) { + my_symbol->option_3 = separator; + } error_number = ZBarcode_Encode(my_symbol, (unsigned char*) optarg, strlen(optarg)); generated = 1; if (error_number != 0) { @@ -754,9 +795,11 @@ int main(int argc, char **argv) { break; case 'i': /* Take data from file */ - if (fullmultibyte && is_fullmultibyte(my_symbol)) { - my_symbol->option_3 = ZINT_FULL_MULTIBYTE; - } + if (fullmultibyte && is_fullmultibyte(my_symbol)) { + my_symbol->option_3 = ZINT_FULL_MULTIBYTE; + } else if (separator && is_stackable(my_symbol->symbology)) { + my_symbol->option_3 = separator; + } if (batch_mode == 0) { error_number = ZBarcode_Encode_File(my_symbol, optarg); generated = 1; @@ -824,4 +867,3 @@ int main(int argc, char **argv) { return error_number; } - diff --git a/frontend_qt/grpCodablockF.ui b/frontend_qt/grpCodablockF.ui index a8bd8247..8663bb28 100644 --- a/frontend_qt/grpCodablockF.ui +++ b/frontend_qt/grpCodablockF.ui @@ -16,129 +16,337 @@ - - + + - Set Symbol Height (Rows) + S&ymbol Width (Columns) + + + cmbCbfWidth - - - - Set Symbol Width (Columns) - - - false - - - - + - 6 + Default - 7 + 9 (4 data) - 8 + 10 (5 data) - 9 + 11 (6 data) - 10 + 12 (7 data) - 11 + 13 (8 data) - 12 + 14 (9 data) - 13 + 15 (10 data) - 14 + 16 (11 data) - 15 + 17 (12 data) - 16 + 18 (13 data) - 17 + 19 (14 data) - 18 + 20 (15 data) - 19 + 21 (16 data) - 20 + 22 (17 data) - 21 + 23 (18 data) - 22 + 24 (19 data) - 23 + 25 (20 data) - 24 + 26 (21 data) - 25 + 27 (22 data) + + + + + 28 (23 data) + + + + + 29 (24 data) + + + + + 30 (25 data) + + + + + 31 (26 data) + + + + + 32 (27 data) + + + + + 33 (28 data) + + + + + 34 (29 data) + + + + + 35 (30 data) + + + + + 36 (31 data) + + + + + 37 (32 data) + + + + + 38 (33 data) + + + + + 39 (34 data) + + + + + 40 (35 data) + + + + + 41 (36 data) + + + + + 42 (37 data) + + + + + 43 (38 data) + + + + + 44 (39 data) + + + + + 45 (40 data) + + + + + 46 (41 data) + + + + + 47 (42 data) + + + + + 48 (43 data) + + + + + 49 (44 data) + + + + + 50 (45 data) + + + + + 51 (46 data) + + + + + 52 (47 data) + + + + + 53 (48 data) + + + + + 54 (49 data) + + + + + 55 (50 data) + + + + + 56 (51 data) + + + + + 57 (52 data) + + + + + 58 (53 data) + + + + + 59 (54 data) + + + + + 60 (55 data) + + + + + 61 (56 data) + + + + + 62 (57 data) + + + + + 63 (58 data) + + + + + 64 (59 data) + + + + + 65 (60 data) + + + + + 66 (61 data) + + + + + 67 (62 data) - + + + + Symbo&l Height (Rows) + + + cmbCbfHeight + + + + + + + Default + + 1 @@ -264,29 +472,185 @@ 25 + + + 26 + + + + + 27 + + + + + 28 + + + + + 29 + + + + + 30 + + + + + 31 + + + + + 32 + + + + + 33 + + + + + 34 + + + + + 35 + + + + + 36 + + + + + 37 + + + + + 38 + + + + + 39 + + + + + 40 + + + + + 41 + + + + + 42 + + + + + 43 + + + + + 44 + + - - + + - Automatic Size + Row Separator Height - - true + + cmbCbfRowSepHeight + + + + + Default (2 X) + + + + + 1 X + + + + + 2 X + + + + + 3 X + + + + + 4 X + + + + + + + + Encoding Mode + + + + QLayout::SetMinimumSize + + + + + Standard Mode + + + true + + + + + + + HIBC Codabloc&k-F Mode + + + + + + Qt::Vertical + + QSizePolicy::Minimum + 20 - 40 + 43 diff --git a/frontend_qt/mainwindow.cpp b/frontend_qt/mainwindow.cpp index e634c3c9..27c4b2f5 100644 --- a/frontend_qt/mainwindow.cpp +++ b/frontend_qt/mainwindow.cpp @@ -13,6 +13,7 @@ * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ +/* vim: set ts=4 sw=4 et : */ #include #include @@ -526,11 +527,11 @@ void MainWindow::change_options() m_optionWidget=uiload.load(&file); file.close(); tabMain->insertTab(1,m_optionWidget,tr("Codablock-F")); - connect(m_optionWidget->findChild("radCbfAutosize"), SIGNAL(toggled( bool )), SLOT(update_preview())); - connect(m_optionWidget->findChild("radCbfSetWidth"), SIGNAL(toggled( bool )), SLOT(update_preview())); - connect(m_optionWidget->findChild("radCbfSetHeight"), SIGNAL(toggled( bool )), SLOT(update_preview())); connect(m_optionWidget->findChild("cmbCbfWidth"), SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); connect(m_optionWidget->findChild("cmbCbfHeight"), SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); + connect(m_optionWidget->findChild("cmbCbfRowSepHeight"), SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); + connect(m_optionWidget->findChild("radCbfStand"), SIGNAL(clicked( bool )), SLOT(update_preview())); + connect(m_optionWidget->findChild("radCbfHIBC"), SIGNAL(clicked( bool )), SLOT(update_preview())); } if(metaObject()->enumerator(0).value(bstyle->currentIndex()) == BARCODE_DATAMATRIX) @@ -769,6 +770,7 @@ void MainWindow::update_preview() { int width = view->geometry().width(); int height = view->geometry().height(); + int item_val; //m_bc.ar=(Zint::QZint::AspectRatioMode)1; if(chkComposite->isChecked() == true) { @@ -779,6 +781,7 @@ void MainWindow::update_preview() } m_bc.bc.setSecurityLevel(0); m_bc.bc.setWidth(0); + m_bc.bc.setOption3(0); m_bc.bc.setInputMode(UNICODE_MODE); m_bc.bc.setHideText(0); if(chkHRTHide->isChecked() == false) { @@ -945,14 +948,27 @@ void MainWindow::update_preview() m_bc.bc.setInputMode(GS1_MODE); break; - case BARCODE_CODABLOCKF: + case BARCODE_CODABLOCKF: + if (m_optionWidget->findChild("radCbfHIBC")->isChecked()) { + m_bc.bc.setSymbol(BARCODE_HIBC_BLOCKF); + } else { m_bc.bc.setSymbol(BARCODE_CODABLOCKF); - if(m_optionWidget->findChild("radCbfSetWidth")->isChecked()) - m_bc.bc.setWidth(m_optionWidget->findChild("cmbCbfWidth")->currentIndex() + 6); - // Height selection uses option 1 in zint_symbol - if(m_optionWidget->findChild("radCbfSetHeight")->isChecked()) - m_bc.bc.setSecurityLevel(m_optionWidget->findChild("cmbCbfHeight")->currentIndex() + 1); - break; + } + item_val = m_optionWidget->findChild("cmbCbfWidth")->currentIndex(); + if (item_val) { + m_bc.bc.setWidth(item_val - 1 + 9); + } + // Height selection uses option 1 in zint_symbol + item_val = m_optionWidget->findChild("cmbCbfHeight")->currentIndex(); + if (item_val) { + m_bc.bc.setSecurityLevel(item_val); + } + // Row separator height selection uses option 3 in zint_symbol + item_val = m_optionWidget->findChild("cmbCbfRowSepHeight")->currentIndex(); + if (item_val) { + m_bc.bc.setOption3(item_val); + } + break; case BARCODE_DATAMATRIX: m_bc.bc.setSecurityLevel(1);