From 1630a4e374633ed7bd1db69df88352f592cf5455 Mon Sep 17 00:00:00 2001 From: Mindaugas Kavaliauskas Date: Fri, 12 Nov 2010 22:05:45 +0000 Subject: [PATCH] 2010-11-13 00:05 UTC+0300 Mindaugas Kavaliauskas (dbtopas/at/dbtopas.lt) + harbour/contrib/hbzebra/datamtrx.c * harbour/contrib/hbzebra/hbzebra.hbp * harbour/contrib/hbzebra/hbzebra.ch + added DataMatrix 2D barcode support ; implemented ASCII encoding only. This is enough for most real life applications, but it is only a minor part of available codeword encodings. I just unable to implement without docs. Reverse engineering of black and white dots take a lot of time for 2D barcodes, so I've dropped this idea. If someone has full ISO/IEC 16022:2006 specification, I can implement the rest. * harbour/contrib/hbzebra/tests/testcair.prg + added DataMatrix test ; Please, add it to other backend tests * harbour/contrib/hbzebra/core.c * changed bitbuffer logic a little * harbour/contrib/hbzebra/pdf417.c * comment added * small cleanup --- harbour/ChangeLog | 23 + harbour/contrib/hbzebra/core.c | 6 +- harbour/contrib/hbzebra/datamtrx.c | 504 +++++++++++++++++++++ harbour/contrib/hbzebra/hbzebra.ch | 26 +- harbour/contrib/hbzebra/hbzebra.hbp | 1 + harbour/contrib/hbzebra/pdf417.c | 4 +- harbour/contrib/hbzebra/tests/testcair.prg | 50 +- 7 files changed, 575 insertions(+), 39 deletions(-) create mode 100644 harbour/contrib/hbzebra/datamtrx.c diff --git a/harbour/ChangeLog b/harbour/ChangeLog index d52ac90407..ab2dbacacd 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -16,6 +16,29 @@ The license applies to all entries newer than 2009-04-28. */ +2010-11-13 00:05 UTC+0300 Mindaugas Kavaliauskas (dbtopas/at/dbtopas.lt) + + harbour/contrib/hbzebra/datamtrx.c + * harbour/contrib/hbzebra/hbzebra.hbp + * harbour/contrib/hbzebra/hbzebra.ch + + added DataMatrix 2D barcode support + ; implemented ASCII encoding only. This is enough for most real + life applications, but it is only a minor part of available + codeword encodings. I just unable to implement without docs. + Reverse engineering of black and white dots take a lot of time + for 2D barcodes, so I've dropped this idea. If someone has + full ISO/IEC 16022:2006 specification, I can implement the rest. + + * harbour/contrib/hbzebra/tests/testcair.prg + + added DataMatrix test + ; Please, add it to other backend tests + + * harbour/contrib/hbzebra/core.c + * changed bitbuffer logic a little + + * harbour/contrib/hbzebra/pdf417.c + * comment added + * small cleanup + 2010-11-12 12:41 UTC+0100 Viktor Szakats (harbour.01 syenar.hu) * contrib/hbzebra/tests/testhpdf.prg ! Cleaned up output order. Patch thanks to Tamas. diff --git a/harbour/contrib/hbzebra/core.c b/harbour/contrib/hbzebra/core.c index 8726208d6c..48d60d921c 100644 --- a/harbour/contrib/hbzebra/core.c +++ b/harbour/contrib/hbzebra/core.c @@ -86,6 +86,9 @@ void hb_bitbuffer_set( PHB_BITBUFFER pBitBuffer, HB_SIZE nPos, HB_BOOL fValue ) * ( pBitBuffer->pBuffer + ( nPos >> 3 ) ) |= 1 << ( nPos & 0x7 ); else * ( pBitBuffer->pBuffer + ( nPos >> 3 ) ) &= ~ ( 1 << ( nPos & 0x7 ) ); + + if( pBitBuffer->nLen <= nPos ) + pBitBuffer->nLen = nPos + 1; } void hb_bitbuffer_cat_int( PHB_BITBUFFER pBitBuffer, int iValue, int iLen ) @@ -105,10 +108,7 @@ void hb_bitbuffer_cat_int( PHB_BITBUFFER pBitBuffer, int iValue, int iLen ) /* TODO: optimize */ for( i = 0; i < iLen; i++ ) - { hb_bitbuffer_set( pBitBuffer, pBitBuffer->nLen, iValue & ( 1 << i ) ); - pBitBuffer->nLen++; - } } HB_SIZE hb_bitbuffer_len( PHB_BITBUFFER pBitBuffer ) diff --git a/harbour/contrib/hbzebra/datamtrx.c b/harbour/contrib/hbzebra/datamtrx.c new file mode 100644 index 0000000000..ac89e0e3ef --- /dev/null +++ b/harbour/contrib/hbzebra/datamtrx.c @@ -0,0 +1,504 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Zebra barcode library + * + * Copyright 2010 Mindaugas Kavaliauskas + * www - http://harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +/* + DataMatrix is ISO/IEC 16022:2006 + + Some info links: + http://www.gs1.org/docs/barcodes/GS1_DataMatrix_Introduction_and_technical_overview.pdf + http://www.aipsys.com/dmintro.htm + + Open source projects, that implements DataMatrix: + http://www.datenfreihafen.org/projects/iec16022.html + http://www.libdmtx.org/ + http://www.codeproject.com/Articles/66495/DataMatrixNet-ported-to-Compact-Framework.aspx + + Online encoder: + http://www.bcgen.com/datamatrix-barcode-creator.html + http://www.bcmaker.com/demos/datamatrix.php + + Online decoder: + http://www.datasymbol.com/barcode-recognition-sdk/barcode-reader/online-barcode-decoder.html + +*/ + +#include "hbzebra.h" +#include "hbapiitm.h" +#include "hbapierr.h" + + +#define PADDING 129 + +#define SIZE_COUNT 30 + +typedef struct +{ + int iRow; + int iCol; + int iRegionRow; + int iRegionCol; + int iDataSize; + int iBlockSize; + int iBlockErrorSize; +} DATAMATRIX_SIZE, * PDATAMATRIX_SIZE; + + +static DATAMATRIX_SIZE s_size[ SIZE_COUNT ] = { + { 10, 10, 10, 10, 3, 3, 5 }, + { 12, 12, 12, 12, 5, 5, 7 }, + { 8, 18, 8, 18, 5, 5, 7 }, + { 14, 14, 14, 14, 8, 8, 10 }, + { 8, 32, 8, 16, 10, 10, 11 }, + { 16, 16, 16, 16, 12, 12, 12 }, + { 12, 26, 12, 26, 16, 16, 14 }, + { 18, 18, 18, 18, 18, 18, 14 }, + { 20, 20, 20, 20, 22, 22, 18 }, + { 12, 36, 12, 18, 22, 22, 18 }, + { 22, 22, 22, 22, 30, 30, 20 }, + { 16, 36, 16, 18, 32, 32, 24 }, + { 24, 24, 24, 24, 36, 36, 24 }, + { 26, 26, 26, 26, 44, 44, 28 }, + { 16, 48, 16, 24, 49, 49, 28 }, + { 32, 32, 16, 16, 62, 62, 36 }, + { 36, 36, 18, 18, 86, 86, 42 }, + { 40, 40, 20, 20, 114, 114, 48 }, + { 44, 44, 22, 22, 144, 144, 56 }, + { 48, 48, 24, 24, 174, 174, 68 }, + { 52, 52, 26, 26, 204, 102, 42 }, + { 64, 64, 16, 16, 280, 140, 56 }, + { 72, 72, 18, 18, 368, 92, 36 }, + { 80, 80, 20, 20, 456, 114, 48 }, + { 88, 88, 22, 22, 576, 144, 56 }, + { 96, 96, 24, 24, 696, 174, 68 }, + {104, 104, 26, 26, 816, 136, 56 }, + {120, 120, 20, 20, 1050, 175, 68 }, + {132, 132, 22, 22, 1304, 163, 62 }, + {144, 144, 24, 24, 1558, 156, 62 }}; + + +static int _datamatrix_isdigit( char ch ) +{ + return '0' <= ch && ch <= '9'; +} + +static int _datamatrix_encode( const char * szCode, int iLen, char * pCW ) +{ + int i, iPos = 0; + for( i = 0; i < iLen; i++ ) + { + if( _datamatrix_isdigit( szCode[ i ] ) && i < iLen - 1 && _datamatrix_isdigit( szCode[ i + 1 ] ) ) + { + pCW[ iPos++ ] = ( szCode[ i ] - '0' ) * 10 + szCode[ i + 1 ] - '0' + 130; + i++; + } + else + pCW[ iPos++ ] = szCode[ i ] + 1; + } + return iPos; +} + + + +static void _reed_solomon_encode( unsigned char * pData, int iDataLen, unsigned char * pEC, int iECLen, int * pPoly, int * pExp, int * pLog, int iMod ) +{ + int i, j; + unsigned char iM; + + for( i = 0; i < iECLen; i++ ) + pEC[ i ] = 0; + + for( i = 0; i < iDataLen; i++ ) + { + iM = pData[ i ] ^ pEC[ iECLen - 1 ]; + for( j = iECLen - 1; j > 0; j-- ) + { + if( iM && pPoly[ j ] ) + pEC[ j ] = pEC[ j - 1 ] ^ pExp[ ( pLog[ iM ] + pLog[ pPoly[ j ] ] ) % iMod ]; + else + pEC[ j ] = pEC[ j - 1 ]; + } + if( iM && pPoly[ 0 ] ) + pEC[ 0 ] = pExp[ ( pLog[ iM ] + pLog[ pPoly[ 0 ] ] ) % iMod ]; + else + pEC[ 0 ] = 0; + } +} + +static void _datamatrix_reed_solomon( char * pData, PDATAMATRIX_SIZE pSize ) +{ + int * pPoly, * pExp, * pLog; + int i, j, iBits, iMod, iPoly, iECLen, iIndex, iBlocks; + + /* Init Galois field. Parameters: iPoly */ + iPoly = 0x12D; + + j = iPoly; + for( iBits = 0; j > 1; iBits++ ) + j >>= 1; + + iMod = ( 1 << iBits ) - 1; + pExp = ( int * ) hb_xgrab( sizeof( int ) * iMod ); /* exponent function */ + pLog = ( int * ) hb_xgrab( sizeof( int ) * ( iMod + 1 ) ); /* logarithm function */ + j = 1; + for( i = 0; i < iMod; i++ ) + { + pExp[ i ] = j; + pLog[ j ] = i; + j <<= 1; + if( j & ( 1 << iBits ) ) + j ^= iPoly; + } + + /* Init Reed-Solomonn encode. Parameters: iECLen, iIndex */ + iECLen = pSize->iBlockErrorSize; + iIndex = 1; + + pPoly = ( int * ) hb_xgrab( sizeof( int ) * ( iECLen + 1 ) ); + pPoly[ 0 ] = 1; + for( i = 1; i <= iECLen; i++ ) + { + pPoly[ i ] = 1; + for( j = i - 1; j > 0; j-- ) + { + if( pPoly[ j ] ) + pPoly[ j ] = pExp[ ( pLog[ pPoly[ j ] ] + iIndex ) % iMod ]; + + pPoly[ j ] ^= pPoly[ j - 1 ]; + } + pPoly[ 0 ] = pExp[ ( pLog[ pPoly[ 0 ] ] + iIndex ) % iMod ]; + iIndex++; + } + + /* Divide data into blocks and do Reed-Solomon encoding for each block */ + + iBlocks = ( pSize->iDataSize + 2 ) / pSize->iBlockSize; + for( i = 0; i < iBlocks; i++ ) + { + unsigned char data[ 256 ], ecc[ 80 ]; + int k = 0; + + /* Copy to temporary buffer */ + for( j = i; j < pSize->iDataSize; j += iBlocks ) + data[ k++ ] = ( unsigned char ) pData[ j ]; + + /* Calculate Reed-Solomon ECC for one block */ + _reed_solomon_encode( data, k, ecc, pSize->iBlockErrorSize, pPoly, pExp, pLog, iMod ); + + /* Copy ECC to codeword array */ + k = pSize->iBlockErrorSize; + for( j = i; j < pSize->iBlockErrorSize * iBlocks; j += iBlocks ) + pData[ pSize->iDataSize + j ] = ( char ) ecc[ --k ]; + } + + hb_xfree( pExp ); + hb_xfree( pLog ); + hb_xfree( pPoly ); +} + + +static void _datamatrix_place_bit( int * pArr, int iPRow, int iPCol, int iR, int iC, int iValue ) +{ + if( iR < 0 ) + { + iR += iPRow; + iC += 4 - ( ( iPRow + 4 ) % 8 ); + } + if( iC < 0 ) + { + iC += iPCol; + iR += 4 - ( ( iPCol + 4 ) % 8 ); + } + pArr[ iR * iPCol + iC ] = iValue; +} + +static void _datamatrix_place( int * pArr, int iPRow, int iPCol, int iR, int iC, int iIndex ) +{ + _datamatrix_place_bit( pArr, iPRow, iPCol, iR - 2, iC - 2, ( iIndex << 3 ) + 7 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, iR - 2, iC - 1, ( iIndex << 3 ) + 6 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, iR - 1, iC - 2, ( iIndex << 3 ) + 5 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, iR - 1, iC - 1, ( iIndex << 3 ) + 4 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, iR - 1, iC - 0, ( iIndex << 3 ) + 3 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, iR - 0, iC - 2, ( iIndex << 3 ) + 2 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, iR - 0, iC - 1, ( iIndex << 3 ) + 1 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, iR - 0, iC - 0, ( iIndex << 3 ) + 0 ); +} + +static void _datamatrix_place_a( int * pArr, int iPRow, int iPCol, int iIndex ) +{ + _datamatrix_place_bit( pArr, iPRow, iPCol, iPRow - 1, 0, ( iIndex << 3 ) + 7 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, iPRow - 1, 1, ( iIndex << 3 ) + 6 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, iPRow - 1, 2, ( iIndex << 3 ) + 5 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 0, iPCol - 2, ( iIndex << 3 ) + 4 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 0, iPCol - 1, ( iIndex << 3 ) + 3 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 1, iPCol - 1, ( iIndex << 3 ) + 2 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 2, iPCol - 1, ( iIndex << 3 ) + 1 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 3, iPCol - 1, ( iIndex << 3 ) + 0 ); +} + +static void _datamatrix_place_b( int * pArr, int iPRow, int iPCol, int iIndex ) +{ + _datamatrix_place_bit( pArr, iPRow, iPCol, iPRow - 3, 0, ( iIndex << 3 ) + 7 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, iPRow - 2, 0, ( iIndex << 3 ) + 6 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, iPRow - 1, 0, ( iIndex << 3 ) + 5 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 0, iPCol - 4, ( iIndex << 3 ) + 4 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 0, iPCol - 3, ( iIndex << 3 ) + 3 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 0, iPCol - 2, ( iIndex << 3 ) + 2 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 0, iPCol - 1, ( iIndex << 3 ) + 1 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 1, iPCol - 1, ( iIndex << 3 ) + 0 ); +} + +static void _datamatrix_place_c( int * pArr, int iPRow, int iPCol, int iIndex ) +{ + _datamatrix_place_bit( pArr, iPRow, iPCol, iPRow - 3, 0, ( iIndex << 3 ) + 7 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, iPRow - 2, 0, ( iIndex << 3 ) + 6 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, iPRow - 1, 0, ( iIndex << 3 ) + 5 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 0, iPCol - 2, ( iIndex << 3 ) + 4 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 0, iPCol - 1, ( iIndex << 3 ) + 3 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 1, iPCol - 1, ( iIndex << 3 ) + 2 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 2, iPCol - 1, ( iIndex << 3 ) + 1 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 3, iPCol - 1, ( iIndex << 3 ) + 0 ); +} + +static void _datamatrix_place_d( int * pArr, int iPRow, int iPCol, int iIndex ) +{ + _datamatrix_place_bit( pArr, iPRow, iPCol, iPRow - 1, 0, ( iIndex << 3 ) + 7 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, iPRow - 1, iPCol - 1, ( iIndex << 3 ) + 6 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 0, iPCol - 3, ( iIndex << 3 ) + 5 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 0, iPCol - 2, ( iIndex << 3 ) + 4 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 0, iPCol - 1, ( iIndex << 3 ) + 3 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 1, iPCol - 3, ( iIndex << 3 ) + 2 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 1, iPCol - 2, ( iIndex << 3 ) + 1 ); + _datamatrix_place_bit( pArr, iPRow, iPCol, 1, iPCol - 1, ( iIndex << 3 ) + 0 ); +} + +static void _datamatrix_do_placement( PHB_BITBUFFER pBits, char * pCW, PDATAMATRIX_SIZE pSize ) +{ + int * pArr; + int i, iR, iC, iPRow, iPCol; + + + /* Calculate placement size without L-patterns and clock tracks */ + iPRow = pSize->iRow - 2 * ( pSize->iRow / pSize->iRegionRow ); + iPCol = pSize->iCol - 2 * ( pSize->iCol / pSize->iRegionCol ); + + pArr = ( int * ) hb_xgrab( sizeof( int ) * iPCol * iPRow ); + hb_xmemset( pArr, 0, sizeof( int ) * iPCol * iPRow ); + + /* Generate placement index array */ + + i = 1; + iR = 4; + iC = 0; + do + { + if( iR == iPRow && iC == 0 ) + _datamatrix_place_a( pArr, iPRow, iPCol, i++ ); + if( iR == iPRow - 2 && iC == 0 && iPCol % 4 ) + _datamatrix_place_b( pArr, iPRow, iPCol, i++ ); + if( iR == iPRow - 2 && iC == 0 && ( iPCol % 8 ) == 4 ) + _datamatrix_place_c( pArr, iPRow, iPCol, i++ ); + if( iR == iPRow - 4 && iC == 2 && ( iPCol % 8 ) == 0 ) + _datamatrix_place_d( pArr, iPRow, iPCol, i++ ); + + do + { + if( iR < iPRow && iC >= 0 && pArr[ iR * iPCol + iC ] == 0 ) + _datamatrix_place( pArr, iPRow, iPCol, iR, iC, i++ ); + iR -= 2; + iC += 2; + } while( iR >= 0 && iC < iPCol ); + + iR++; + iC += 3; + + do + { + if( iR >= 0 && iC < iPCol && pArr[ iR * iPCol + iC ] == 0 ) + _datamatrix_place( pArr, iPRow, iPCol, iR, iC, i++ ); + iR += 2; + iC -= 2; + } while( iR < iPRow && iC >= 0 ); + + iR += 3; + iC++; + } while( iR < iPRow || iC < iPCol ); + + if( pArr[ iPRow * iPCol - 1 ] == 0 ) + pArr[ iPRow * iPCol - 1 ] = pArr[ iPRow * iPCol - iPCol - 2 ] = 1; + + + /* Place codewords */ + + for( iR = 0; iR < iPRow; iR++ ) + { + for( iC = 0; iC < iPCol; iC++ ) + { + i = pArr[ iR * iPCol + iC ]; + if( i == 1 || + ( i > 7 && ( pCW[ ( i >> 3 ) - 1 ] & ( 1 << ( i & 7 ) ) ) ) ) + { + hb_bitbuffer_set( pBits, + ( 1 + iR + 2 * ( iR / ( pSize->iRegionRow - 2 ) ) ) * pSize->iCol + + ( 1 + iC + 2 * ( iC / ( pSize->iRegionCol - 2 ) ) ), 1 ); + } + } + } + hb_xfree( pArr ); +} + +PHB_ZEBRA hb_zebra_create_datamatrix( const char * szCode, HB_SIZE nLen, int iFlags ) +{ + PHB_ZEBRA pZebra; + PDATAMATRIX_SIZE pSize; + char * pCW; + int i, j, iDataCount, iErrorSize, iLen = ( int ) nLen; + + pZebra = hb_zebra_create(); + pZebra->iType = HB_ZEBRA_TYPE_DATAMATRIX; + + if( iLen > 3116 ) + { + pZebra->iError = HB_ZEBRA_ERROR_TOOLARGE; + return pZebra; + } + + for( i = 0; i < iLen; i++ ) + { + if( ( unsigned char ) szCode[ i ] >= 128 ) + { + pZebra->iError = HB_ZEBRA_ERROR_INVALIDCODE; + return pZebra; + } + } + + pCW = ( char * ) hb_xgrab( sizeof( char ) * iLen ); + iDataCount = _datamatrix_encode( szCode, iLen, pCW ); + + pSize = NULL; + for( i = 0; i < SIZE_COUNT; i++ ) + { + if( s_size[ i ].iDataSize >= iDataCount ) + { + if( ( ( iFlags & HB_ZEBRA_FLAG_DATAMATRIX_SQUARE ) && s_size[ i ].iRow == s_size[ i ].iCol ) || + ( ( iFlags & HB_ZEBRA_FLAG_DATAMATRIX_RECTANGLE ) && s_size[ i ].iRow != s_size[ i ].iCol ) || + ( iFlags & ( HB_ZEBRA_FLAG_DATAMATRIX_SQUARE | HB_ZEBRA_FLAG_DATAMATRIX_RECTANGLE ) ) == 0 ) + { + pSize = s_size + i; + break; + } + } + } + if( ! pSize ) + { + hb_xfree( pCW ); + pZebra->iError = HB_ZEBRA_ERROR_INVALIDCODE; + return pZebra; + } + + iErrorSize = ( pSize->iDataSize + 2 ) / pSize->iBlockSize * pSize->iBlockErrorSize; + + pCW = ( char * ) hb_xrealloc( pCW, pSize->iDataSize + iErrorSize ); + for( i = iDataCount; i < pSize->iDataSize; i++ ) + { + pCW[ i ] = PADDING; + } + + /* Reed-Solomon error correction */ + _datamatrix_reed_solomon( pCW, pSize ); + +#if 0 + for( i = 0; i < pSize->iDataSize + iErrorSize; i++ ) + { + HB_TRACE( HB_TR_ALWAYS, ("cw=%d", ( unsigned char ) pCW[ i ] )); + } +#endif + + pZebra->iCol = pSize->iCol; + pZebra->szCode = hb_strdup( "" ); + pZebra->pBits = hb_bitbuffer_create(); + + /* allocate bitbuffer */ + hb_bitbuffer_set( pZebra->pBits, pSize->iCol * pSize->iRow - 1, 0 ); + + /* Draw L-finder pattern and clock track */ + for( j = 0; j < pSize->iRow; j += pSize->iRegionRow ) + { + for( i = 0; i < pSize->iCol; i++ ) + hb_bitbuffer_set( pZebra->pBits, ( j + pSize->iRegionCol - 1 ) * pSize->iCol + i, 1 ); + for( i = 0; i < pSize->iCol; i += 2 ) + hb_bitbuffer_set( pZebra->pBits, j * pSize->iCol + i, 1 ); + } + for( i = 0; i < pSize->iCol; i += pSize->iRegionCol ) + { + for( j = 1; j < pSize->iRow; j++ ) + hb_bitbuffer_set( pZebra->pBits, j * pSize->iCol + i, 1 ); + for( j = 1; j < pSize->iRow; j += 2 ) + hb_bitbuffer_set( pZebra->pBits, j * pSize->iCol + i + pSize->iRegionCol - 1, 1 ); + } + + /* And now the most crazy part - placement */ + _datamatrix_do_placement( pZebra->pBits, pCW, pSize ); + + hb_xfree( pCW ); + return pZebra; +} + +HB_FUNC( HB_ZEBRA_CREATE_DATAMATRIX ) +{ + PHB_ITEM pItem = hb_param( 1, HB_IT_STRING ); + if( pItem ) + { + hb_zebra_ret( hb_zebra_create_datamatrix( hb_itemGetCPtr( pItem ), hb_itemGetCLen( pItem ), hb_parni( 2 ) ) ); + } + else + hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); +} diff --git a/harbour/contrib/hbzebra/hbzebra.ch b/harbour/contrib/hbzebra/hbzebra.ch index c95fa2aa74..69cab701f0 100644 --- a/harbour/contrib/hbzebra/hbzebra.ch +++ b/harbour/contrib/hbzebra/hbzebra.ch @@ -69,6 +69,7 @@ #define HB_ZEBRA_TYPE_MSI 11 #define HB_ZEBRA_TYPE_PDF417 257 +#define HB_ZEBRA_TYPE_DATAMATRIX 258 /* Generate errors */ #define HB_ZEBRA_ERROR_INVALIDCODE 1 @@ -88,16 +89,19 @@ /* Draw flags */ /* Barcode dependent flags */ -#define HB_ZEBRA_FLAG_PDF417_TRUNCATED 0x0100 -#define HB_ZEBRA_FLAG_PDF417_LEVEL_MASK 0xF000 -#define HB_ZEBRA_FLAG_PDF417_LEVEL0 0x1000 -#define HB_ZEBRA_FLAG_PDF417_LEVEL1 0x2000 -#define HB_ZEBRA_FLAG_PDF417_LEVEL2 0x3000 -#define HB_ZEBRA_FLAG_PDF417_LEVEL3 0x4000 -#define HB_ZEBRA_FLAG_PDF417_LEVEL4 0x5000 -#define HB_ZEBRA_FLAG_PDF417_LEVEL5 0x6000 -#define HB_ZEBRA_FLAG_PDF417_LEVEL6 0x7000 -#define HB_ZEBRA_FLAG_PDF417_LEVEL7 0x8000 -#define HB_ZEBRA_FLAG_PDF417_LEVEL8 0x9000 +#define HB_ZEBRA_FLAG_PDF417_TRUNCATED 0x0100 +#define HB_ZEBRA_FLAG_PDF417_LEVEL_MASK 0xF000 +#define HB_ZEBRA_FLAG_PDF417_LEVEL0 0x1000 +#define HB_ZEBRA_FLAG_PDF417_LEVEL1 0x2000 +#define HB_ZEBRA_FLAG_PDF417_LEVEL2 0x3000 +#define HB_ZEBRA_FLAG_PDF417_LEVEL3 0x4000 +#define HB_ZEBRA_FLAG_PDF417_LEVEL4 0x5000 +#define HB_ZEBRA_FLAG_PDF417_LEVEL5 0x6000 +#define HB_ZEBRA_FLAG_PDF417_LEVEL6 0x7000 +#define HB_ZEBRA_FLAG_PDF417_LEVEL7 0x8000 +#define HB_ZEBRA_FLAG_PDF417_LEVEL8 0x9000 + +#define HB_ZEBRA_FLAG_DATAMATRIX_SQUARE 0x0100 +#define HB_ZEBRA_FLAG_DATAMATRIX_RECTANGLE 0x0200 #endif /* HB_ZEBRA_CH_ */ diff --git a/harbour/contrib/hbzebra/hbzebra.hbp b/harbour/contrib/hbzebra/hbzebra.hbp index 8ee55d0141..7090eccb26 100644 --- a/harbour/contrib/hbzebra/hbzebra.hbp +++ b/harbour/contrib/hbzebra/hbzebra.hbp @@ -25,3 +25,4 @@ eanupc.c itf.c msi.c pdf417.c +datamtrx.c diff --git a/harbour/contrib/hbzebra/pdf417.c b/harbour/contrib/hbzebra/pdf417.c index 2e510910d9..232d1797c3 100644 --- a/harbour/contrib/hbzebra/pdf417.c +++ b/harbour/contrib/hbzebra/pdf417.c @@ -51,6 +51,8 @@ */ /* + PDF417 is ISO/IEC 15438:2006 + Good short PDF417 description: http://grandzebu.net/index.php?page=/informatique/codbar-en/pdf417.htm @@ -1249,8 +1251,6 @@ PHB_ZEBRA hb_zebra_create_pdf417( const char * szCode, HB_SIZE nLen, int iFlags, int * pCW; int i, j, iLevel, iRowCount, iDataCount, iCount, iLen = ( int ) nLen; - HB_SYMBOL_UNUSED( iFlags ); - pZebra = hb_zebra_create(); pZebra->iType = HB_ZEBRA_TYPE_PDF417; diff --git a/harbour/contrib/hbzebra/tests/testcair.prg b/harbour/contrib/hbzebra/tests/testcair.prg index ac3fa189c1..560c227788 100644 --- a/harbour/contrib/hbzebra/tests/testcair.prg +++ b/harbour/contrib/hbzebra/tests/testcair.prg @@ -17,29 +17,30 @@ PROCEDURE main() cairo_set_font_size( hCairo, 10 ) cairo_set_source_rgb( hCairo, 0, 0, 0 ) - DrawBarcode( hCairo, 20, 1, "EAN13", "477012345678" ) - DrawBarcode( hCairo, 40, 1, "EAN8", "1234567" ) - DrawBarcode( hCairo, 60, 1, "UPCA", "01234567891" ) - DrawBarcode( hCairo, 80, 1, "UPCE", "123456" ) - DrawBarcode( hCairo, 100, 1, "CODE39", "ABC123" ) - DrawBarcode( hCairo, 120, 1, "CODE39", "ABC123", HB_ZEBRA_FLAG_CHECKSUM ) - DrawBarcode( hCairo, 140, 0.5, "CODE39", "ABC123", HB_ZEBRA_FLAG_CHECKSUM + HB_ZEBRA_FLAG_WIDE2_5 ) - DrawBarcode( hCairo, 160, 1, "CODE39", "ABC123", HB_ZEBRA_FLAG_CHECKSUM + HB_ZEBRA_FLAG_WIDE3 ) - DrawBarcode( hCairo, 180, 1, "ITF", "1234", HB_ZEBRA_FLAG_WIDE3 ) - DrawBarcode( hCairo, 200, 1, "ITF", "12345678901", HB_ZEBRA_FLAG_CHECKSUM ) - DrawBarcode( hCairo, 220, 1, "MSI", "1234" ) - DrawBarcode( hCairo, 240, 1, "MSI", "1234", HB_ZEBRA_FLAG_CHECKSUM + HB_ZEBRA_FLAG_WIDE3 ) - DrawBarcode( hCairo, 260, 1, "MSI", "1234567", HB_ZEBRA_FLAG_CHECKSUM ) - DrawBarcode( hCairo, 280, 1, "CODABAR", "40156", HB_ZEBRA_FLAG_WIDE3 ) - DrawBarcode( hCairo, 300, 1, "CODABAR", "-1234", HB_ZEBRA_FLAG_WIDE3 ) - DrawBarcode( hCairo, 320, 1, "CODE93", "ABC-123" ) - DrawBarcode( hCairo, 340, 1, "CODE93", "TEST93" ) - DrawBarcode( hCairo, 360, 1, "CODE11", "12", HB_ZEBRA_FLAG_WIDE3 ) - DrawBarcode( hCairo, 380, 1, "CODE11", "1234567890", HB_ZEBRA_FLAG_CHECKSUM + HB_ZEBRA_FLAG_WIDE3 ) - DrawBarcode( hCairo, 400, 1, "CODE128", "Code 128") - DrawBarcode( hCairo, 420, 1, "CODE128", "1234567890") - DrawBarcode( hCairo, 440, 1, "CODE128", "Wikipedia") - DrawBarcode( hCairo, 460, 1, "PDF417", "Hello, World of Harbour!!! It's 2D barcode PDF417 :)" ) + DrawBarcode( hCairo, 20, 1, "EAN13", "477012345678" ) + DrawBarcode( hCairo, 40, 1, "EAN8", "1234567" ) + DrawBarcode( hCairo, 60, 1, "UPCA", "01234567891" ) + DrawBarcode( hCairo, 80, 1, "UPCE", "123456" ) + DrawBarcode( hCairo, 100, 1, "CODE39", "ABC123" ) + DrawBarcode( hCairo, 120, 1, "CODE39", "ABC123", HB_ZEBRA_FLAG_CHECKSUM ) + DrawBarcode( hCairo, 140, 0.5, "CODE39", "ABC123", HB_ZEBRA_FLAG_CHECKSUM + HB_ZEBRA_FLAG_WIDE2_5 ) + DrawBarcode( hCairo, 160, 1, "CODE39", "ABC123", HB_ZEBRA_FLAG_CHECKSUM + HB_ZEBRA_FLAG_WIDE3 ) + DrawBarcode( hCairo, 180, 1, "ITF", "1234", HB_ZEBRA_FLAG_WIDE3 ) + DrawBarcode( hCairo, 200, 1, "ITF", "12345678901", HB_ZEBRA_FLAG_CHECKSUM ) + DrawBarcode( hCairo, 220, 1, "MSI", "1234" ) + DrawBarcode( hCairo, 240, 1, "MSI", "1234", HB_ZEBRA_FLAG_CHECKSUM + HB_ZEBRA_FLAG_WIDE3 ) + DrawBarcode( hCairo, 260, 1, "MSI", "1234567", HB_ZEBRA_FLAG_CHECKSUM ) + DrawBarcode( hCairo, 280, 1, "CODABAR", "40156", HB_ZEBRA_FLAG_WIDE3 ) + DrawBarcode( hCairo, 300, 1, "CODABAR", "-1234", HB_ZEBRA_FLAG_WIDE3 ) + DrawBarcode( hCairo, 320, 1, "CODE93", "ABC-123" ) + DrawBarcode( hCairo, 340, 1, "CODE93", "TEST93" ) + DrawBarcode( hCairo, 360, 1, "CODE11", "12", HB_ZEBRA_FLAG_WIDE3 ) + DrawBarcode( hCairo, 380, 1, "CODE11", "1234567890", HB_ZEBRA_FLAG_CHECKSUM + HB_ZEBRA_FLAG_WIDE3 ) + DrawBarcode( hCairo, 400, 1, "CODE128", "Code 128") + DrawBarcode( hCairo, 420, 1, "CODE128", "1234567890") + DrawBarcode( hCairo, 440, 1, "CODE128", "Wikipedia") + DrawBarcode( hCairo, 460, 1, "PDF417", "Hello, World of Harbour!!! It's 2D barcode PDF417 :)" ) + DrawBarcode( hCairo, 540, 1, "DATAMATRIX", "Hello, World of Harbour!!! It's 2D barcode DataMatrix :)") cairo_destroy( hCairo ) cairo_surface_write_to_png( hSurface, "testcair.png" ) @@ -75,6 +76,9 @@ PROCEDURE DrawBarcode( hCairo, nY, nLineWidth, cType, cCode, nFlags ) ELSEIF cType == "PDF417" hZebra := hb_zebra_create_pdf417( cCode, nFlags ) nLineHeight := nLineWidth * 3 + ELSEIF cType == "DATAMATRIX" + hZebra := hb_zebra_create_datamatrix( cCode, nFlags ) + nLineHeight := nLineWidth ENDIF IF hZebra != NIL IF hb_zebra_geterror( hZebra ) == 0