diff --git a/harbour/ChangeLog b/harbour/ChangeLog index c5d93fe666..6e3679f507 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -16,6 +16,28 @@ The license applies to all entries newer than 2009-04-28. */ +2011-12-23 18:00 UTC+0200 Mindaugas Kavaliauskas (dbtopas/at/dbtopas.lt) + + contrib/hbzebra/qrcode.c + * contrib/hbzebra/hbzebra.ch + * contrib/hbzebra/hbzebra.hbp + * contrib/hbzebra/hbzebra.hbx + + QR Code + ; Christmas gift for Harbour project :) + ; TODO: encoding optimisation using mode switching + + * contrib/hbzebra/hbzebra.h + * contrib/hbzebra/core.c + + hb_bitbuffer_buffer(), hb_bitbuffer_not(), hb_bitbuffer_cat_int_rev() + * formatting + + * contrib/hbzebra/tests/testcair.prg + * contrib/hbzebra/tests/testhpdf.prg + * contrib/hbzebra/tests/testwin.prg + * updated to include QR Code + + * contrib/hbzebra/datamtrx.c + * minor modification: code text support + 2011-12-23 10:43 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * harbour/include/hbapicdp.h * harbour/src/rtl/cdpapi.c diff --git a/harbour/contrib/hbzebra/core.c b/harbour/contrib/hbzebra/core.c index 48d60d921c..0e667e2fa3 100644 --- a/harbour/contrib/hbzebra/core.c +++ b/harbour/contrib/hbzebra/core.c @@ -65,6 +65,7 @@ PHB_BITBUFFER hb_bitbuffer_create( void ) return pBitBuffer; } + void hb_bitbuffer_destroy( PHB_BITBUFFER pBitBuffer ) { if( pBitBuffer->pBuffer ) @@ -72,12 +73,32 @@ void hb_bitbuffer_destroy( PHB_BITBUFFER pBitBuffer ) hb_xfree( pBitBuffer ); } + +HB_SIZE hb_bitbuffer_len( PHB_BITBUFFER pBitBuffer ) +{ + return pBitBuffer->nLen; +} + + +unsigned char * hb_bitbuffer_buffer( PHB_BITBUFFER pBitBuffer ) +{ + return pBitBuffer->pBuffer; +} + + +HB_BOOL hb_bitbuffer_get( PHB_BITBUFFER pBitBuffer, HB_SIZE nPos ) +{ + return nPos > pBitBuffer->nLen ? HB_FALSE : + ( ( pBitBuffer->pBuffer[ nPos >> 3 ] >> ( nPos & 7 ) ) & 1 ); +} + + void hb_bitbuffer_set( PHB_BITBUFFER pBitBuffer, HB_SIZE nPos, HB_BOOL fValue ) { if( pBitBuffer->nAlloc * 8 <= nPos ) { HB_SIZE nNewAlloc = ( ( pBitBuffer->nAlloc >> 1 ) + nPos + 8 ) / 8; - pBitBuffer->pBuffer = ( HB_BYTE * ) hb_xrealloc( pBitBuffer->pBuffer, nNewAlloc ); + pBitBuffer->pBuffer = ( unsigned char * ) hb_xrealloc( pBitBuffer->pBuffer, nNewAlloc ); hb_xmemset( pBitBuffer->pBuffer + pBitBuffer->nAlloc, 0, nNewAlloc - pBitBuffer->nAlloc ); pBitBuffer->nAlloc = nNewAlloc; } @@ -91,6 +112,21 @@ void hb_bitbuffer_set( PHB_BITBUFFER pBitBuffer, HB_SIZE nPos, HB_BOOL fValue ) pBitBuffer->nLen = nPos + 1; } + +void hb_bitbuffer_not( PHB_BITBUFFER pBitBuffer, HB_SIZE nPos ) +{ + if( pBitBuffer->nAlloc * 8 <= nPos ) + { + HB_SIZE nNewAlloc = ( ( pBitBuffer->nAlloc >> 1 ) + nPos + 8 ) / 8; + pBitBuffer->pBuffer = ( unsigned char * ) hb_xrealloc( pBitBuffer->pBuffer, nNewAlloc ); + hb_xmemset( pBitBuffer->pBuffer + pBitBuffer->nAlloc, 0, nNewAlloc - pBitBuffer->nAlloc ); + pBitBuffer->nAlloc = nNewAlloc; + } + + * ( pBitBuffer->pBuffer + ( nPos >> 3 ) ) ^= 1 << ( nPos & 0x7 ); +} + + void hb_bitbuffer_cat_int( PHB_BITBUFFER pBitBuffer, int iValue, int iLen ) { int i; @@ -98,7 +134,7 @@ void hb_bitbuffer_cat_int( PHB_BITBUFFER pBitBuffer, int iValue, int iLen ) if( ( pBitBuffer->nLen + iLen ) >= pBitBuffer->nAlloc * 8 ) { int nNewAlloc = pBitBuffer->nAlloc + ( ( pBitBuffer->nAlloc >> 1 ) + iLen + 7 ) / 8; - pBitBuffer->pBuffer = ( HB_BYTE * ) hb_xrealloc( pBitBuffer->pBuffer, nNewAlloc ); + pBitBuffer->pBuffer = ( unsigned char * ) hb_xrealloc( pBitBuffer->pBuffer, nNewAlloc ); hb_xmemset( pBitBuffer->pBuffer + pBitBuffer->nAlloc, 0, nNewAlloc - pBitBuffer->nAlloc ); pBitBuffer->nAlloc = nNewAlloc; } @@ -111,16 +147,27 @@ void hb_bitbuffer_cat_int( PHB_BITBUFFER pBitBuffer, int iValue, int iLen ) hb_bitbuffer_set( pBitBuffer, pBitBuffer->nLen, iValue & ( 1 << i ) ); } -HB_SIZE hb_bitbuffer_len( PHB_BITBUFFER pBitBuffer ) + +void hb_bitbuffer_cat_int_rev( PHB_BITBUFFER pBitBuffer, int iValue, int iLen ) { - return pBitBuffer->nLen; + int i; + + if( ( pBitBuffer->nLen + iLen ) >= pBitBuffer->nAlloc * 8 ) + { + int nNewAlloc = pBitBuffer->nAlloc + ( ( pBitBuffer->nAlloc >> 1 ) + iLen + 7 ) / 8; + pBitBuffer->pBuffer = ( unsigned char * ) hb_xrealloc( pBitBuffer->pBuffer, nNewAlloc ); + hb_xmemset( pBitBuffer->pBuffer + pBitBuffer->nAlloc, 0, nNewAlloc - pBitBuffer->nAlloc ); + pBitBuffer->nAlloc = nNewAlloc; + } + + if( ( unsigned int ) iLen > sizeof( int ) * 8 ) + iLen = sizeof( int ) * 8; + + /* TODO: optimize */ + for( i = iLen - 1; i >= 0; i-- ) + hb_bitbuffer_set( pBitBuffer, pBitBuffer->nLen, iValue & ( 1 << i ) ); } -HB_BOOL hb_bitbuffer_get( PHB_BITBUFFER pBitBuffer, HB_SIZE nPos ) -{ - return nPos > pBitBuffer->nLen ? HB_FALSE : - ( ( pBitBuffer->pBuffer[ nPos >> 3 ] >> ( nPos & 7 ) ) & 1 ); -} /* ================ GC pointer ================ */ @@ -135,6 +182,7 @@ static HB_GARBAGE_FUNC( hb_zebra_destructor ) } } + static const HB_GC_FUNCS s_gcZebraFuncs = { hb_zebra_destructor, @@ -148,6 +196,7 @@ PHB_ZEBRA hb_zebraItemGet( PHB_ITEM pItem ) return ppZebra ? *ppZebra : NULL; } + PHB_ITEM hb_zebraItemPut( PHB_ITEM pItem, PHB_ZEBRA pZebra ) { PHB_ZEBRA * ppZebra = ( PHB_ZEBRA * ) hb_gcAllocate( sizeof( PHB_ZEBRA ), &s_gcZebraFuncs ); @@ -156,6 +205,7 @@ PHB_ITEM hb_zebraItemPut( PHB_ITEM pItem, PHB_ZEBRA pZebra ) return hb_itemPutPtrGC( pItem, ppZebra ); } + void hb_zebraItemClear( PHB_ITEM pItem ) { PHB_ZEBRA * ppZebra = ( PHB_ZEBRA * ) hb_itemGetPtrGC( pItem, &s_gcZebraFuncs ); @@ -164,6 +214,7 @@ void hb_zebraItemClear( PHB_ITEM pItem ) * ppZebra = NULL; } + PHB_ZEBRA hb_zebra_param( int iParam ) { PHB_ZEBRA * ppZebra = ( PHB_ZEBRA * ) hb_parptrGC( &s_gcZebraFuncs, iParam ); @@ -175,6 +226,7 @@ PHB_ZEBRA hb_zebra_param( int iParam ) return NULL; } + void hb_zebra_ret( PHB_ZEBRA pZebra ) { hb_zebraItemPut( hb_stackReturnItem(), pZebra ); @@ -190,6 +242,7 @@ PHB_ZEBRA hb_zebra_create( void ) return pZebra; } + void hb_zebra_destroy( PHB_ZEBRA pZebra ) { if( pZebra->szCode ) @@ -199,6 +252,7 @@ void hb_zebra_destroy( PHB_ZEBRA pZebra ) hb_xfree( pZebra ); } + HB_FUNC( HB_ZEBRA_DESTROY ) { PHB_ZEBRA pZebra = hb_zebra_param( 1 ); @@ -209,6 +263,7 @@ HB_FUNC( HB_ZEBRA_DESTROY ) } } + HB_FUNC( HB_ZEBRA_GETERROR ) { PHB_ZEBRA pZebra = hb_zebra_param( 1 ); @@ -218,6 +273,7 @@ HB_FUNC( HB_ZEBRA_GETERROR ) } } + HB_FUNC( HB_ZEBRA_GETCODE ) { PHB_ZEBRA pZebra = hb_zebra_param( 1 ); diff --git a/harbour/contrib/hbzebra/datamtrx.c b/harbour/contrib/hbzebra/datamtrx.c index 359bd0e178..36533be7b9 100644 --- a/harbour/contrib/hbzebra/datamtrx.c +++ b/harbour/contrib/hbzebra/datamtrx.c @@ -465,7 +465,8 @@ PHB_ZEBRA hb_zebra_create_datamatrix( const char * szCode, HB_SIZE nLen, int iFl #endif pZebra->iCol = pSize->iCol; - pZebra->szCode = hb_strdup( "" ); + + pZebra->szCode = hb_strdup( szCode ); pZebra->pBits = hb_bitbuffer_create(); /* allocate bitbuffer */ diff --git a/harbour/contrib/hbzebra/hbzebra.ch b/harbour/contrib/hbzebra/hbzebra.ch index 69cab701f0..caec479e7f 100644 --- a/harbour/contrib/hbzebra/hbzebra.ch +++ b/harbour/contrib/hbzebra/hbzebra.ch @@ -70,6 +70,7 @@ #define HB_ZEBRA_TYPE_PDF417 257 #define HB_ZEBRA_TYPE_DATAMATRIX 258 +#define HB_ZEBRA_TYPE_QRCODE 259 /* Generate errors */ #define HB_ZEBRA_ERROR_INVALIDCODE 1 @@ -104,4 +105,10 @@ #define HB_ZEBRA_FLAG_DATAMATRIX_SQUARE 0x0100 #define HB_ZEBRA_FLAG_DATAMATRIX_RECTANGLE 0x0200 +#define HB_ZEBRA_FLAG_QR_LEVEL_MASK 0x0700 +#define HB_ZEBRA_FLAG_QR_LEVEL_L 0x0100 +#define HB_ZEBRA_FLAG_QR_LEVEL_M 0x0200 +#define HB_ZEBRA_FLAG_QR_LEVEL_Q 0x0300 +#define HB_ZEBRA_FLAG_QR_LEVEL_H 0x0400 + #endif /* HB_ZEBRA_CH_ */ diff --git a/harbour/contrib/hbzebra/hbzebra.h b/harbour/contrib/hbzebra/hbzebra.h index 2135081bb7..c5f27538e6 100644 --- a/harbour/contrib/hbzebra/hbzebra.h +++ b/harbour/contrib/hbzebra/hbzebra.h @@ -58,10 +58,10 @@ typedef struct { - HB_BYTE * pBuffer; - HB_SIZE nLen; - HB_SIZE nAlloc; - void * pCargo; + unsigned char * pBuffer; + HB_SIZE nLen; + HB_SIZE nAlloc; + void * pCargo; } HB_BITBUFFER, * PHB_BITBUFFER; typedef struct @@ -75,12 +75,15 @@ typedef struct HB_EXTERN_BEGIN -extern HB_EXPORT PHB_BITBUFFER hb_bitbuffer_create( void ); -extern HB_EXPORT void hb_bitbuffer_destroy( PHB_BITBUFFER pBitBuffer ); -extern HB_EXPORT void hb_bitbuffer_set( PHB_BITBUFFER pBitBuffer, HB_SIZE nPos, HB_BOOL fValue ); -extern HB_EXPORT void hb_bitbuffer_cat_int( PHB_BITBUFFER pBitBuffer, int iValue, int iLen ); -extern HB_EXPORT HB_SIZE hb_bitbuffer_len( PHB_BITBUFFER pBitBuffer ); -extern HB_EXPORT HB_BOOL hb_bitbuffer_get( PHB_BITBUFFER pBitBuffer, HB_SIZE nPos ); +extern HB_EXPORT PHB_BITBUFFER hb_bitbuffer_create( void ); +extern HB_EXPORT void hb_bitbuffer_destroy( PHB_BITBUFFER pBitBuffer ); +extern HB_EXPORT HB_SIZE hb_bitbuffer_len( PHB_BITBUFFER pBitBuffer ); +extern HB_EXPORT unsigned char * hb_bitbuffer_buffer( PHB_BITBUFFER pBitBuffer ); +extern HB_EXPORT HB_BOOL hb_bitbuffer_get( PHB_BITBUFFER pBitBuffer, HB_SIZE nPos ); +extern HB_EXPORT void hb_bitbuffer_set( PHB_BITBUFFER pBitBuffer, HB_SIZE nPos, HB_BOOL fValue ); +extern HB_EXPORT void hb_bitbuffer_not( PHB_BITBUFFER pBitBuffer, HB_SIZE nPos ); +extern HB_EXPORT void hb_bitbuffer_cat_int( PHB_BITBUFFER pBitBuffer, int iValue, int iLen ); +extern HB_EXPORT void hb_bitbuffer_cat_int_rev( PHB_BITBUFFER pBitBuffer, int iValue, int iLen ); extern HB_EXPORT PHB_ZEBRA hb_zebra_create( void ); extern HB_EXPORT void hb_zebra_destroy( PHB_ZEBRA pZebra ); diff --git a/harbour/contrib/hbzebra/hbzebra.hbp b/harbour/contrib/hbzebra/hbzebra.hbp index f272a64694..18e87c8e81 100644 --- a/harbour/contrib/hbzebra/hbzebra.hbp +++ b/harbour/contrib/hbzebra/hbzebra.hbp @@ -29,3 +29,4 @@ itf.c msi.c pdf417.c datamtrx.c +qrcode.c diff --git a/harbour/contrib/hbzebra/hbzebra.hbx b/harbour/contrib/hbzebra/hbzebra.hbx index 537d3d249f..f3449ad2b8 100644 --- a/harbour/contrib/hbzebra/hbzebra.hbx +++ b/harbour/contrib/hbzebra/hbzebra.hbx @@ -36,6 +36,7 @@ DYNAMIC HB_ZEBRA_CREATE_EAN8 DYNAMIC HB_ZEBRA_CREATE_ITF DYNAMIC HB_ZEBRA_CREATE_MSI DYNAMIC HB_ZEBRA_CREATE_PDF417 +DYNAMIC HB_ZEBRA_CREATE_QRCODE DYNAMIC HB_ZEBRA_CREATE_UPCA DYNAMIC HB_ZEBRA_CREATE_UPCE DYNAMIC HB_ZEBRA_DESTROY diff --git a/harbour/contrib/hbzebra/qrcode.c b/harbour/contrib/hbzebra/qrcode.c new file mode 100644 index 0000000000..dedd148dd6 --- /dev/null +++ b/harbour/contrib/hbzebra/qrcode.c @@ -0,0 +1,1313 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Zebra barcode library + * + * Copyright 2011 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. + * + */ + +/* + QR Code is ISO/IEC18004 + + JIS-X-0510 QR Code standard in Japaneese language :) + http://sourceforge.jp/projects/qrcode/docs/qrcode_specification_ja/en/1/qrcode_specification_ja.pdf + +http://en.wikipedia.org/wiki/QR_Code +http://www.denso-wave.com/qrcode/index-e.html +http://www.itsc.org.sg/pdf/synthesis08/Three_QR_Code.pdf +http://www.qrme.co.uk/qr-code-resources/understanding-a-qr-code.html +http://www.swetake.com/qr/index-e.html +http://www.codeproject.com/KB/cs/qrcode.aspx +http://sourceforge.jp/projects/reedsolomon +http://twit88.com/home/ +http://qrcode.sourceforge.jp/ +http://zxing.org/w/decode.jspx Online decoder +http://blog.qr4.nl/Online-QR-Code_Decoder.aspx Online decoder (not all codes are decoded) +http://www.thonky.com/qr-code-tutorial/ Tutorial +http://code.google.com/p/zxing/ Java library +http://goqr.me/ Online encode +http://www.pclviewer.com/rs2/calculator.html Reed-solomon ECC calculator +http://raidenii.net/files/datasheets/misc/qr_code.pdf + +*/ + +#include "hbzebra.h" +#include "hbapi.h" +#include "hbapiitm.h" +#include "hbapierr.h" + +/* #define DEBUG_CODE */ + +typedef struct +{ + unsigned char uiCount; + unsigned char uiData; + unsigned char uiECC; +} QRBLOCKPARAM; + +typedef struct +{ + unsigned int uiECC; + QRBLOCKPARAM block[ 2 ]; +} QRLEVEL, * PQRLEVEL; + +typedef struct +{ + unsigned int uiTotal; /* total number of codewords */ + QRLEVEL level[ 4 ]; +} QRVERSION, * PQRVERSION; + +static const QRVERSION s_version[] = +{ + { 26, {{ 7, {{ 1, 19, 7}, { 0, 0, 0}}}, /* 1 2 * 2 */ + { 10, {{ 1, 16, 10}, { 0, 0, 0}}}, /* 4 * 2 */ + { 13, {{ 1, 13, 13}, { 0, 0, 0}}}, /* 6 * 2 */ + { 17, {{ 1, 9, 17}, { 0, 0, 0}}}}}, /* 8 * 2 */ + { 44, {{ 10, {{ 1, 34, 10}, { 0, 0, 0}}}, /* 2 4 * 2 */ + { 16, {{ 1, 28, 16}, { 0, 0, 0}}}, + { 22, {{ 1, 22, 22}, { 0, 0, 0}}}, + { 28, {{ 1, 16, 28}, { 0, 0, 0}}}}}, + { 70, {{ 15, {{ 1, 55, 15}, { 0, 0, 0}}}, /* 3 7 * 2 */ + { 26, {{ 1, 44, 26}, { 0, 0, 0}}}, + { 36, {{ 2, 17, 18}, { 0, 0, 0}}}, + { 44, {{ 2, 13, 22}, { 0, 0, 0}}}}}, + { 100, {{ 20, {{ 1, 80, 20}, { 0, 0, 0}}}, /* 4 */ + { 36, {{ 2, 32, 18}, { 0, 0, 0}}}, + { 52, {{ 2, 24, 26}, { 0, 0, 0}}}, + { 64, {{ 4, 9, 16}, { 0, 0, 0}}}}}, + { 134, {{ 26, {{ 1, 108, 26}, { 0, 0, 0}}}, /* 5 */ + { 48, {{ 2, 43, 24}, { 0, 0, 0}}}, + { 72, {{ 2, 15, 18}, { 2, 16, 18}}}, + { 88, {{ 2, 11, 22}, { 2, 12, 22}}}}}, + { 172, {{ 36, {{ 2, 68, 18}, { 0, 0, 0}}}, /* 6 */ + { 64, {{ 4, 27, 16}, { 0, 0, 0}}}, + { 96, {{ 4, 19, 24}, { 0, 0, 0}}}, + { 112, {{ 4, 15, 28}, { 0, 0, 0}}}}}, + { 196, {{ 40, {{ 2, 78, 20}, { 0, 0, 0}}}, /* 7 */ + { 72, {{ 4, 31, 18}, { 0, 0, 0}}}, + { 108, {{ 2, 14, 18}, { 4, 15, 18}}}, + { 130, {{ 4, 13, 26}, { 1, 14, 26}}}}}, + { 242, {{ 48, {{ 2, 97, 24}, { 0, 0, 0}}}, /* 8 */ + { 88, {{ 2, 38, 22}, { 2, 39, 22}}}, + { 132, {{ 4, 18, 22}, { 2, 19, 22}}}, + { 156, {{ 4, 14, 26}, { 2, 15, 26}}}}}, + { 292, {{ 60, {{ 2, 116, 30}, { 0, 0, 0}}}, /* 9 */ + { 110, {{ 3, 36, 22}, { 2, 37, 22}}}, + { 160, {{ 4, 16, 20}, { 4, 17, 20}}}, + { 192, {{ 4, 12, 24}, { 4, 13, 24}}}}}, + { 346, {{ 72, {{ 2, 68, 18}, { 2, 69, 18}}}, /* 10 */ + { 130, {{ 4, 43, 26}, { 1, 44, 26}}}, + { 192, {{ 6, 19, 24}, { 2, 20, 24}}}, + { 224, {{ 6, 15, 28}, { 2, 16, 28}}}}}, + { 404, {{ 80, {{ 4, 81, 20}, { 0, 0, 0}}}, /* 11 */ + { 150, {{ 1, 50, 30}, { 4, 51, 30}}}, + { 224, {{ 4, 22, 28}, { 4, 23, 28}}}, + { 264, {{ 3, 12, 24}, { 8, 13, 24}}}}}, + { 466, {{ 96, {{ 2, 92, 24}, { 2, 93, 24}}}, /* 12 */ + { 176, {{ 6, 36, 22}, { 2, 37, 22}}}, + { 260, {{ 4, 20, 26}, { 6, 21, 26}}}, + { 308, {{ 7, 14, 28}, { 4, 15, 28}}}}}, + { 532, {{ 104, {{ 4, 107, 26}, { 0, 0, 0}}}, /* 13 */ + { 198, {{ 8, 37, 22}, { 1, 38, 22}}}, + { 288, {{ 8, 20, 24}, { 4, 21, 24}}}, + { 352, {{12, 11, 22}, { 4, 12, 22}}}}}, + { 581, {{ 120, {{ 3, 115, 30}, { 1, 116, 30}}}, /* 14 */ + { 216, {{ 4, 40, 24}, { 5, 41, 24}}}, + { 320, {{11, 16, 20}, { 5, 17, 20}}}, + { 384, {{11, 12, 24}, { 5, 13, 24}}}}}, + { 655, {{ 132, {{ 5, 87, 22}, { 1, 88, 22}}}, /* 15 */ + { 240, {{ 5, 41, 24}, { 5, 42, 24}}}, + { 360, {{ 5, 24, 30}, { 7, 25, 30}}}, + { 432, {{11, 12, 24}, { 7, 13, 24}}}}}, + { 733, {{ 144, {{ 5, 98, 24}, { 1, 99, 24}}}, /* 16 */ + { 280, {{ 7, 45, 28}, { 3, 46, 28}}}, + { 408, {{15, 19, 24}, { 2, 20, 24}}}, + { 480, {{ 3, 15, 30}, {13, 16, 30}}}}}, + { 815, {{ 168, {{ 1, 107, 28}, { 5, 108, 28}}}, /* 17 */ + { 308, {{10, 46, 28}, { 1, 47, 28}}}, + { 448, {{ 1, 22, 28}, {15, 23, 28}}}, + { 532, {{ 2, 14, 28}, {17, 15, 28}}}}}, + { 901, {{ 180, {{ 5, 120, 30}, { 1, 121, 30}}}, /* 18 */ + { 338, {{ 9, 43, 26}, { 4, 44, 26}}}, + { 504, {{17, 22, 28}, { 1, 23, 28}}}, + { 588, {{ 2, 14, 28}, {19, 15, 28}}}}}, + { 991, {{ 196, {{ 3, 113, 28}, { 4, 114, 28}}}, /* 19 */ + { 364, {{ 3, 44, 26}, {11, 45, 26}}}, + { 546, {{17, 21, 26}, { 4, 22, 26}}}, + { 650, {{ 9, 13, 26}, {16, 14, 26}}}}}, + {1085, {{ 224, {{ 3, 107, 28}, { 5, 108, 28}}}, /* 20 */ + { 416, {{ 3, 41, 26}, {13, 42, 26}}}, + { 600, {{15, 24, 30}, { 5, 25, 30}}}, + { 700, {{15, 15, 28}, {10, 16, 28}}}}}, + {1156, {{ 224, {{ 4, 116, 28}, { 4, 117, 28}}}, /* 21 */ + { 442, {{17, 42, 26}, { 0, 0, 0}}}, + { 644, {{17, 22, 28}, { 6, 23, 28}}}, + { 750, {{19, 16, 30}, { 6, 17, 30}}}}}, + {1258, {{ 252, {{ 2, 111, 28}, { 7, 112, 28}}}, /* 22 */ + { 476, {{17, 46, 28}, { 0, 0, 0}}}, + { 690, {{ 7, 24, 30}, {16, 25, 30}}}, + { 816, {{34, 13, 24}, { 0, 0, 0}}}}}, + {1364, {{ 270, {{ 4, 121, 30}, { 5, 122, 30}}}, /* 23 */ + { 504, {{ 4, 47, 28}, {14, 48, 28}}}, + { 750, {{11, 24, 30}, {14, 25, 30}}}, + { 900, {{16, 15, 30}, {14, 16, 30}}}}}, + {1474, {{ 300, {{ 6, 117, 30}, { 4, 118, 30}}}, /* 24 */ + { 560, {{ 6, 45, 28}, {14, 46, 28}}}, + { 810, {{11, 24, 30}, {16, 25, 30}}}, + { 960, {{30, 16, 30}, { 2, 17, 30}}}}}, + {1588, {{ 312, {{ 8, 106, 26}, { 4, 107, 26}}}, /* 25 */ + { 588, {{ 8, 47, 28}, {13, 48, 28}}}, + { 870, {{ 7, 24, 30}, {22, 25, 30}}}, + {1050, {{22, 15, 30}, {13, 16, 30}}}}}, + {1706, {{ 336, {{10, 114, 28}, { 2, 115, 28}}}, /* 26 */ + { 644, {{19, 46, 28}, { 4, 47, 28}}}, + { 952, {{28, 22, 28}, { 6, 23, 28}}}, + {1110, {{33, 16, 30}, { 4, 17, 30}}}}}, + {1828, {{ 360, {{ 8, 122, 30}, { 4, 123, 30}}}, /* 27 */ + { 700, {{22, 45, 28}, { 3, 46, 28}}}, + {1020, {{ 8, 23, 30}, {26, 24, 30}}}, + {1200, {{12, 15, 30}, {28, 16, 30}}}}}, + {1921, {{ 390, {{ 3, 117, 30}, {10, 118, 30}}}, /* 28 */ + { 728, {{ 3, 45, 28}, {23, 46, 28}}}, + {1050, {{ 4, 24, 30}, {31, 25, 30}}}, + {1260, {{11, 15, 30}, {31, 16, 30}}}}}, + {2051, {{ 420, {{ 7, 116, 30}, { 7, 117, 30}}}, /* 29 */ + { 784, {{21, 45, 28}, { 7, 46, 28}}}, + {1140, {{ 1, 23, 30}, {37, 24, 30}}}, + {1350, {{19, 15, 30}, {26, 16, 30}}}}}, + {2185, {{ 450, {{ 5, 115, 30}, {10, 116, 30}}}, /* 30 */ + { 812, {{19, 47, 28}, {10, 48, 28}}}, + {1200, {{15, 24, 30}, {25, 25, 30}}}, + {1440, {{23, 15, 30}, {25, 16, 30}}}}}, + {2323, {{ 480, {{13, 115, 30}, { 3, 116, 30}}}, /* 31 */ + { 868, {{ 2, 46, 28}, {29, 47, 28}}}, + {1290, {{42, 24, 30}, { 1, 25, 30}}}, + {1530, {{23, 15, 30}, {28, 16, 30}}}}}, + {2465, {{ 510, {{17, 115, 30}, { 0, 0, 0}}}, /* 32 */ + { 924, {{10, 46, 28}, {23, 47, 28}}}, + {1350, {{10, 24, 30}, {35, 25, 30}}}, + {1620, {{19, 15, 30}, {35, 16, 30}}}}}, + {2611, {{ 540, {{17, 115, 30}, { 1, 116, 30}}}, /* 33 */ + { 980, {{14, 46, 28}, {21, 47, 28}}}, + {1440, {{29, 24, 30}, {19, 25, 30}}}, + {1710, {{11, 15, 30}, {46, 16, 30}}}}}, + {2761, {{ 570, {{13, 115, 30}, { 6, 116, 30}}}, /* 34 */ + {1036, {{14, 46, 28}, {23, 47, 28}}}, + {1530, {{44, 24, 30}, { 7, 25, 30}}}, + {1800, {{59, 16, 30}, { 1, 17, 30}}}}}, + {2876, {{ 570, {{12, 121, 30}, { 7, 122, 30}}}, /* 35 */ + {1064, {{12, 47, 28}, {26, 48, 28}}}, + {1590, {{39, 24, 30}, {14, 25, 30}}}, + {1890, {{22, 15, 30}, {41, 16, 30}}}}}, + {3034, {{ 600, {{ 6, 121, 30}, {14, 122, 30}}}, /* 36 */ + {1120, {{ 6, 47, 28}, {34, 48, 28}}}, + {1680, {{46, 24, 30}, {10, 25, 30}}}, + {1980, {{ 2, 15, 30}, {64, 16, 30}}}}}, + {3196, {{ 630, {{17, 122, 30}, { 4, 123, 30}}}, /* 37 */ + {1204, {{29, 46, 28}, {14, 47, 28}}}, + {1770, {{49, 24, 30}, {10, 25, 30}}}, + {2100, {{24, 15, 30}, {46, 16, 30}}}}}, + {3362, {{ 660, {{ 4, 122, 30}, {18, 123, 30}}}, /* 38 */ + {1260, {{13, 46, 28}, {32, 47, 28}}}, + {1860, {{48, 24, 30}, {14, 25, 30}}}, + {2220, {{42, 15, 30}, {32, 16, 30}}}}}, + {3532, {{ 720, {{20, 117, 30}, { 4, 118, 30}}}, /* 39 */ + {1316, {{40, 47, 28}, { 7, 48, 28}}}, + {1950, {{43, 24, 30}, {22, 25, 30}}}, + {2310, {{10, 15, 30}, {67, 16, 30}}}}}, + {3706, {{ 750, {{19, 118, 30}, { 6, 119, 30}}}, /* 40 */ + {1372, {{18, 47, 28}, {31, 48, 28}}}, + {2040, {{34, 24, 30}, {34, 25, 30}}}, + {2430, {{20, 15, 30}, {61, 16, 30}}}}} +}; + + +static const unsigned char s_rev[256] = +{ +#define R2(n) n, n + 2*64, n + 1*64, n + 3*64 +#define R4(n) R2(n), R2(n + 2*16), R2(n + 1*16), R2(n + 3*16) +#define R6(n) R4(n), R4(n + 2*4 ), R4(n + 1*4 ), R4(n + 3*4 ) + R6(0), R6(2), R6(1), R6(3) +}; + + +/* zero terminated align patterns positions */ +static unsigned char s_align01[] = { 0 }; +static unsigned char s_align02[] = { 6, 18, 0 }; +static unsigned char s_align03[] = { 6, 22, 0 }; +static unsigned char s_align04[] = { 6, 26, 0 }; +static unsigned char s_align05[] = { 6, 30, 0 }; +static unsigned char s_align06[] = { 6, 34, 0 }; +static unsigned char s_align07[] = { 6, 22, 38, 0 }; +static unsigned char s_align08[] = { 6, 24, 42, 0 }; +static unsigned char s_align09[] = { 6, 26, 46, 0 }; +static unsigned char s_align00[] = { 6, 28, 50, 0 }; +static unsigned char s_align11[] = { 6, 30, 54, 0 }; +static unsigned char s_align12[] = { 6, 32, 58, 0 }; +static unsigned char s_align13[] = { 6, 34, 62, 0 }; +static unsigned char s_align14[] = { 6, 26, 46, 66, 0 }; +static unsigned char s_align15[] = { 6, 26, 48, 70, 0 }; +static unsigned char s_align16[] = { 6, 26, 50, 74, 0 }; +static unsigned char s_align17[] = { 6, 30, 54, 78, 0 }; +static unsigned char s_align18[] = { 6, 30, 56, 82, 0 }; +static unsigned char s_align19[] = { 6, 30, 58, 86, 0 }; +static unsigned char s_align10[] = { 6, 34, 62, 90, 0 }; +static unsigned char s_align21[] = { 6, 28, 50, 72, 94, 0 }; +static unsigned char s_align22[] = { 6, 26, 50, 74, 98, 0 }; +static unsigned char s_align23[] = { 6, 30, 54, 78, 102, 0 }; +static unsigned char s_align24[] = { 6, 28, 54, 80, 106, 0 }; +static unsigned char s_align25[] = { 6, 32, 58, 84, 110, 0 }; +static unsigned char s_align26[] = { 6, 30, 58, 86, 114, 0 }; +static unsigned char s_align27[] = { 6, 34, 62, 90, 118, 0 }; +static unsigned char s_align28[] = { 6, 26, 50, 74, 98, 122, 0 }; +static unsigned char s_align29[] = { 6, 30, 54, 78, 102, 126, 0 }; +static unsigned char s_align20[] = { 6, 26, 52, 78, 104, 130, 0 }; +static unsigned char s_align31[] = { 6, 30, 56, 82, 108, 134, 0 }; +static unsigned char s_align32[] = { 6, 34, 60, 86, 112, 138, 0 }; +static unsigned char s_align33[] = { 6, 30, 58, 86, 114, 142, 0 }; +static unsigned char s_align34[] = { 6, 34, 62, 90, 118, 146, 0 }; +static unsigned char s_align35[] = { 6, 30, 54, 78, 102, 126, 150, 0 }; +static unsigned char s_align36[] = { 6, 24, 50, 76, 102, 128, 154, 0 }; +static unsigned char s_align37[] = { 6, 28, 54, 80, 106, 132, 158, 0 }; +static unsigned char s_align38[] = { 6, 32, 58, 84, 110, 136, 162, 0 }; +static unsigned char s_align39[] = { 6, 26, 54, 82, 110, 138, 166, 0 }; +static unsigned char s_align40[] = { 6, 30, 58, 86, 114, 142, 170, 0 }; + +static unsigned char * s_align[ 40 ] = { + s_align01, + s_align02, + s_align03, + s_align04, + s_align05, + s_align06, + s_align07, + s_align08, + s_align09, + s_align00, + s_align11, + s_align12, + s_align13, + s_align14, + s_align15, + s_align16, + s_align17, + s_align18, + s_align19, + s_align10, + s_align21, + s_align22, + s_align23, + s_align24, + s_align25, + s_align26, + s_align27, + s_align28, + s_align29, + s_align20, + s_align31, + s_align32, + s_align33, + s_align34, + s_align35, + s_align36, + s_align37, + s_align38, + s_align39, + s_align40 }; + + +#ifdef DEBUG_CODE +static int _qr_check_version_table( void ) +{ + const QRVERSION * pQRVersion; + int iV, iL; + unsigned int uiSumD, uiSumE; + + for( iV = 1; iV <= 40; iV++ ) + { + pQRVersion = & s_version[ iV - 1 ]; + for( iL = 0; iL < 4; iL++ ) + { + uiSumE = ( unsigned int ) ( pQRVersion->level[ iL ].block[ 0 ].uiCount ) * ( pQRVersion->level[ iL ].block[ 0 ].uiECC ) + + ( unsigned int ) ( pQRVersion->level[ iL ].block[ 1 ].uiCount ) * ( pQRVersion->level[ iL ].block[ 1 ].uiECC ); + if( uiSumE != pQRVersion->level[ iL ].uiECC ) + return iV + 10000 + (iL + 1) * 1000; + + uiSumD = ( unsigned int ) ( pQRVersion->level[ iL ].block[ 0 ].uiCount ) * ( pQRVersion->level[ iL ].block[ 0 ].uiData ) + + ( unsigned int ) ( pQRVersion->level[ iL ].block[ 1 ].uiCount ) * ( pQRVersion->level[ iL ].block[ 1 ].uiData ); + if( uiSumD + uiSumE != pQRVersion->uiTotal ) + return iV + 20000 + (iL + 1) * 1000; + + if( pQRVersion->level[ iL ].block[ 1 ].uiCount > 0 ) + { + if( pQRVersion->level[ iL ].block[ 0 ].uiData > pQRVersion->level[ iL ].block[ 1 ].uiData ) + return iV + 30000 + (iL + 1) * 1000; + + if( pQRVersion->level[ iL ].block[ 0 ].uiECC != pQRVersion->level[ iL ].block[ 1 ].uiECC ) + return iV + 40000 + (iL + 1) * 1000; + } + } + } + return 0; +} + +HB_FUNC( _QR_CHECK_VERSION_TABLE ) +{ + hb_retni( _qr_check_version_table() ); +} +#endif + + +static int _qr_version_crc( int iVersion ) +{ + int i, iValue, iVersionRev; + + iVersionRev = 0; + for( i = 0; i < 6; i++ ) + { + iVersionRev <<= 1; + if( iVersion & 1 ) + iVersionRev |= 1; + iVersion >>= 1; + } + + iValue = iVersionRev; + for( i = 0; i < 6; i++ ) + { + if( iValue & 1 ) + iValue ^= 0x149F; /* 0x149F - reversed 12-bit polynom */ + iValue >>= 1; + } + iValue <<= 6; + iValue |= iVersionRev; + return iValue; /* 18-bit return value */ +} + + +static int _qr_format_crc( int iLevel, int iMask ) +{ + int i, iValue, iRev; + + iRev = ( ( iLevel & 1 ) ? 0 : 2 ) | ( ( iLevel & 2 ) ? 1 : 0 ); /* 0->1, 1->0, 2->3, 3->2 + reverse bits */ + iRev |= ( ( iMask & 1 ) ? 16 : 0 ) | ( ( iMask & 2 ) ? 8 : 0 ) | ( ( iMask & 4 ) ? 4 : 0 ); /* reverse bits */ + + iValue = iRev; + for( i = 0; i < 5; i++ ) + { + if( iValue & 1 ) + iValue ^= 0x765; /* 0x765 - reversed 10-bit polynom */ + iValue >>= 1; + } + iValue <<= 5; + iValue |= iRev; + return iValue ^ 0x2415; /* 15-bit return value */ +} + + +#ifdef DEBUG_CODE +HB_FUNC( _QR_VERSION_CRC ) +{ + hb_retni( _qr_version_crc( hb_parni( 1 ) ) ); +} + + +HB_FUNC( _QR_FORMAT_CRC ) +{ + hb_retni( _qr_format_crc( hb_parni( 1 ), hb_parni( 2 ) ) ); +} +#endif + + +static int _qr_versionlength( int iVersion ) +{ + return iVersion * 4 + 17; +} + + +static int _qr_fixed( int iVersion, int iRow, int iCol ) +{ + int iLength = _qr_versionlength( iVersion ); + unsigned char * pi, *pj; + + /* position detection markers and versino info */ + if( iRow < 9 && iCol < 9 ) + return 1; + if( iRow < 9 && iCol >= iLength - 8 ) + return 1; + if( iRow >= iLength - 8 && iCol < 9 ) + return 1; + + /* timing patterns */ + if( iRow == 6 || iCol == 6 ) + return 1; + + /* alignment patterns */ + pi = s_align[ iVersion - 1 ]; + for( ; *pi; pi++ ) + { + pj = s_align[ iVersion - 1 ]; + for( ; *pj; pj++ ) + { + if( iRow - 2 <= ( int ) *pi && ( int ) *pi <= iRow + 2 && + iCol - 2 <= ( int ) *pj && ( int ) *pj <= iCol + 2 ) + { + if( ( *pi == 6 && ( int ) *pj > iLength - 10 ) || + ( ( int ) *pi > iLength - 10 && *pj == 6 ) ) + break; + + return 1; + } + } + } + + /* format info */ + if( iVersion >= 7 && + ( ( iCol < 6 && iRow >= iLength - 11 ) || ( iCol >= iLength - 11 && iRow < 6 ) ) ) + return 1; + + return 0; +} + + +static PHB_BITBUFFER _qr_interlace( PHB_BITBUFFER pData, unsigned char * pECC, int iVersion, int iLevel ) +{ + const QRVERSION * pVersion = &s_version[ iVersion - 1 ]; + const QRLEVEL * pLevel = &( pVersion->level[ iLevel ] ); + PHB_BITBUFFER pRet; + HB_BYTE * pDataBuf, * pRetBuf; + unsigned int uiDst, uiSrc, uiPos, uiBlock; + + pRet = hb_bitbuffer_create(); + hb_bitbuffer_set( pRet, pVersion->uiTotal * 8, HB_FALSE ); /* Allocate */ + + pRetBuf = hb_bitbuffer_buffer( pRet ); + pDataBuf = hb_bitbuffer_buffer( pData ); + + uiDst = 0; + for( uiPos = 0; uiPos < ( unsigned int ) pLevel->block[ 0 ].uiData || uiPos < ( unsigned int ) pLevel->block[ 1 ].uiData; uiPos++ ) + { + uiSrc = 0; + for( uiBlock = 0; uiBlock < ( unsigned int ) pLevel->block[ 0 ].uiCount; uiBlock++ ) + { + if( uiPos < ( unsigned int ) pLevel->block[ 0 ].uiData ) + { + pRetBuf[ uiDst++ ] = pDataBuf[ uiPos + uiSrc ]; + } + uiSrc += pLevel->block[ 0 ].uiData; + } + if( pLevel->block[ 1 ].uiCount ) + { + for( uiBlock = 0; uiBlock < ( unsigned int ) pLevel->block[ 1 ].uiCount; uiBlock++ ) + { + pRetBuf[ uiDst++ ] = pDataBuf[ uiPos + uiSrc ]; + uiSrc += pLevel->block[ 1 ].uiData; + } + } + } + + for( uiPos = 0; uiPos < ( unsigned int ) pLevel->block[ 0 ].uiECC; uiPos++ ) + { + uiSrc = 0; + for( uiBlock = 0; uiBlock < ( unsigned int ) pLevel->block[ 0 ].uiCount; uiBlock++ ) + { + if( uiPos < ( unsigned int ) pLevel->block[ 0 ].uiECC ) + { + pRetBuf[ uiDst++ ] = s_rev[ pECC[ uiPos + uiSrc ] ]; + } + uiSrc += pLevel->block[ 0 ].uiECC; + } + if( pLevel->block[ 1 ].uiCount ) + { + for( uiBlock = 0; uiBlock < ( unsigned int ) pLevel->block[ 1 ].uiCount; uiBlock++ ) + { + pRetBuf[ uiDst++ ] = s_rev[ pECC[ uiPos + uiSrc ] ]; + uiSrc += pLevel->block[ 1 ].uiECC; + } + } + } + +#ifdef DEBUG_CODE + if( uiDst != pVersion->uiTotal ) + { + HB_TRACE( HB_TR_ALWAYS, ("ERROR!!! uiDst:%d pVersion->uiTotal:%d", uiDst, pVersion->uiTotal) ) ; + } + + for( uiPos = 0; uiPos < pVersion->uiTotal; uiPos++ ) + { + HB_TRACE( HB_TR_ALWAYS, ("interlaced:%3d %02X", ( int ) s_rev[ ( unsigned char ) pRetBuf[ uiPos ] ], ( int ) s_rev[ ( unsigned char ) pRetBuf[ uiPos ] ]) ) ; + } +#endif + return pRet; +} + + +static int _qr_alphanumeric_no( char ch ) +{ + if( '0' <= ch && ch <= '9' ) + return ch - '0'; + + if( 'A' <= ch && ch <= 'Z' ) + return ch - 'A' + 10; + + switch( ch ) + { + case ' ': + return 36; + case '$': + return 37; + case '%': + return 38; + case '*': + return 39; + case '+': + return 40; + case '-': + return 41; + case '.': + return 42; + case '/': + return 43; + case ':': + return 44; + } + return -1; +} + +static int _qr_cci_len( int iVersion, int iMode ) /* Character Count Indicator */ +{ + if( iMode == 1 ) + return iVersion <= 9 ? 10 : ( iVersion <= 26 ? 12 : 14 ); + if( iMode == 2 ) + return iVersion <= 9 ? 9 : ( iVersion <= 26 ? 11 : 13 ); + if( iMode == 4 ) + return iVersion <= 9 ? 8 : 16; + return 0; +} + + +static int _qr_dataencode( const char * szCode, HB_SIZE nSize, PHB_BITBUFFER pData, int iLevel ) +{ + int i, iVersion, iMode, iLen, iDataLen; + HB_SIZE n; + char ch; + + /* Select encoding mode */ + iMode = 1; /* 1=Numeric, 2=Alphanumeric, 4=8-bit, 8=Kanji. Not modes: 0=termibator, 3=Structured append, 7=ECI, 5=FNC1(1), 9=FNC1(2)*/ + for( n = 0; n < nSize; n++ ) + { + ch = szCode[ n ]; + if( '0' <= ch && ch <= '9' ) + { + } + else if( ( 'A' <= ch && ch <= 'Z' ) || + ch == ' ' || ch == '$' || ch == '%' || ch == '*' || ch == '+' || ch == '-' || ch == '.' || ch == '/' || ch == ':' ) + iMode = 2; + else + { + iMode = 4; + break; + } + } + + /* Calculate data length in bits */ + if( iMode == 1 ) + iLen = ( nSize / 3 ) * 10 + ( ( nSize % 3 ) == 0 ? 0 : ( ( nSize % 3 ) == 1 ? 4 : 7 ) ); + else if( iMode == 2 ) + iLen = ( nSize / 2 ) * 11 + ( nSize % 2 ) * 6; + else if( iMode == 4 ) + iLen = nSize * 8; + + iLen += 4; /* Mode indicator length */ + + + /* Select version */ + for( i = 1; i <= 40; i++ ) + { + iDataLen = ( int ) ( s_version[ i - 1 ].uiTotal - s_version[ i - 1 ].level[ iLevel ].uiECC ); + if( iDataLen * 8 >= iLen + _qr_cci_len( i, iMode ) ) + { + iVersion = i; + break; + } + } + if( i > 40 ) + return 0; /* Too large */ + +#ifdef DEBUG_CODE + HB_TRACE( HB_TR_ALWAYS, ("iMode:%d iLen:%d iDataLen:%d iVersion:%d", iMode, iLen, iDataLen, iVersion) ) ; +#endif + + /* Encode */ + hb_bitbuffer_cat_int_rev( pData, iMode, 4 ); + hb_bitbuffer_cat_int_rev( pData, ( int ) nSize, _qr_cci_len( iVersion, iMode ) ); + if( iMode == 1 ) + { + for( n = 0; n + 2 < nSize; n += 3 ) + { + hb_bitbuffer_cat_int_rev( pData, 100 * ( int )( unsigned char ) ( szCode[ n ] - '0' ) + + 10 * ( int )( unsigned char ) ( szCode[ n + 1 ] - '0' ) + + ( int )( unsigned char ) ( szCode[ n + 2 ] - '0' ), 10 ); + } + if( n + 1 == nSize ) + hb_bitbuffer_cat_int_rev( pData, ( int )( unsigned char ) ( szCode[ n ] - '0' ), 4 ); + else + hb_bitbuffer_cat_int_rev( pData, 10 * ( int )( unsigned char ) ( szCode[ n ] - '0' ) + + ( int )( unsigned char ) ( szCode[ n + 1 ] - '0' ), 7 ); + } + else if( iMode == 2 ) + { + for( n = 0; n + 1 < nSize; n += 2 ) + { + hb_bitbuffer_cat_int_rev( pData, 45 * _qr_alphanumeric_no( szCode[ n ] ) + _qr_alphanumeric_no( szCode[ n + 1 ] ), 11 ); + } + if( n != nSize ) + { + hb_bitbuffer_cat_int_rev( pData, _qr_alphanumeric_no( szCode[ n ] ), 6 ); + } + } + else if( iMode == 4 ) + { + for( n = 0; n < nSize; n++ ) + hb_bitbuffer_cat_int_rev( pData, ( int ) ( unsigned char ) szCode[ n ], 8 ); + } + + /* Terminator */ + if( iDataLen * 8 >= ( int ) hb_bitbuffer_len( pData ) + 4 ) + hb_bitbuffer_cat_int_rev( pData, 0, 4 ); + + /* Padding */ + if( hb_bitbuffer_len( pData ) & 7 ) + hb_bitbuffer_cat_int_rev( pData, 0, 8 - ( hb_bitbuffer_len( pData ) & 7 ) ); + + iLen = iDataLen - hb_bitbuffer_len( pData ) / 8; + for( i = 0; i < iLen; i++ ) + { + hb_bitbuffer_cat_int_rev( pData, ( i & 1 ) ? 0x11 : 0xEC, 8 ); + } + +#ifdef DEBUG_CODE + for( i = 0; i < iDataLen; i++ ) + { + HB_TRACE( HB_TR_ALWAYS, ("data:%3d %02X", s_rev[ * (hb_bitbuffer_buffer(pData) + i) ], s_rev[ * (hb_bitbuffer_buffer(pData) + i) ]) ); + } +#endif + return iVersion; +} + + +static void _reed_solomon_encode( unsigned char * pData, int iDataLen, unsigned char * pECC, int iECCLen, int * pPoly, int * pExp, int * pLog, int iMod ) +{ + int i, j; + unsigned char iM; + + for( i = 0; i < iECCLen; i++ ) + pECC[ i ] = 0; + + for( i = 0; i < iDataLen; i++ ) + { + iM = s_rev[ pData[ i ] ] ^ pECC[ iECCLen - 1 ]; + for( j = iECCLen - 1; j > 0; j-- ) + { + if( iM && pPoly[ j ] ) + pECC[ j ] = ( unsigned char ) ( pECC[ j - 1 ] ^ pExp[ ( pLog[ iM ] + pLog[ pPoly[ j ] ] ) % iMod ] ); + else + pECC[ j ] = pECC[ j - 1 ]; + } + if( iM && pPoly[ 0 ] ) + pECC[ 0 ] = ( unsigned char ) ( pExp[ ( pLog[ iM ] + pLog[ pPoly[ 0 ] ] ) % iMod ] ); + else + pECC[ 0 ] = 0; + } +} + + +static unsigned char * _qr_checksum( PHB_BITBUFFER pData, int iVersion, int iLevel ) +{ + const QRVERSION * pVersion = &s_version[ iVersion - 1 ]; + const QRLEVEL * pLevel = &( pVersion->level[ iLevel ] ); + HB_BYTE * pDataBuf = hb_bitbuffer_buffer( pData ); + int * pPoly, * pExp, * pLog; + int i, j, iBits, iMod, iPoly, iECCLen, iIndex; + unsigned char * pECC, * pECCPtr, ui, ui2; + + /* Init Galois field. Parameters: iPoly */ + iPoly = 0x11D; + + 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; + pLog[ 0 ] = iMod; + 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: iECCLen, iIndex */ + iECCLen = pLevel->block[ 0 ].uiECC; + iIndex = 0; /* why this parameter is different from DataMatrix ??? */ + + pPoly = ( int * ) hb_xgrab( sizeof( int ) * ( iECCLen + 1 ) ); + pPoly[ 0 ] = 1; + for( i = 1; i <= iECCLen; 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++; + } + +#ifdef DEBUG_CODE + for( i = 0; i <= iECCLen; i++ ) + { + HB_TRACE( HB_TR_ALWAYS, ("POLY[%3d %02X]:%3d %02X", i, i, pPoly[ i ], pPoly[ i ]) ) ; + } +#endif + + pECC = ( unsigned char * ) hb_xgrab( pLevel->block[ 0 ].uiECC * ( pLevel->block[ 0 ].uiCount + pLevel->block[ 1 ].uiCount ) ); + pECCPtr = pECC; + + /* Divide data into blocks and do Reed-Solomon encoding for each block */ + for( ui = 0; ui < pLevel->block[ 0 ].uiCount; ui++ ) + { + /* Calculate Reed-Solomon ECC for one block */ + _reed_solomon_encode( pDataBuf, pLevel->block[ 0 ].uiData, pECCPtr, iECCLen, pPoly, pExp, pLog, iMod ); + pDataBuf += pLevel->block[ 0 ].uiData; + for( i = 0; i < iECCLen / 2; i++ ) + { + ui2 = pECCPtr[ i ]; + pECCPtr[ i ] = pECCPtr[ iECCLen - 1 - i ]; + pECCPtr[ iECCLen - 1 - i ] = ui2; + } + pECCPtr += iECCLen; + } + for( ui = 0; ui < pLevel->block[ 1 ].uiCount; ui++ ) + { + /* Calculate Reed-Solomon ECC for one block */ + _reed_solomon_encode( pDataBuf, pLevel->block[ 1 ].uiData, pECCPtr, iECCLen, pPoly, pExp, pLog, iMod ); + pDataBuf += pLevel->block[ 1 ].uiData; + for( i = 0; i < iECCLen / 2; i++ ) + { + ui2 = pECCPtr[ i ]; + pECCPtr[ i ] = pECCPtr[ iECCLen - 1 - i ]; + pECCPtr[ iECCLen - 1 - i ] = ui2; + } + pECCPtr += iECCLen; + } + + hb_xfree( pExp ); + hb_xfree( pLog ); + hb_xfree( pPoly ); + +#ifdef DEBUG_CODE + iECCLen = pLevel->block[ 0 ].uiECC * ( pLevel->block[ 0 ].uiCount + pLevel->block[ 1 ].uiCount ); + for( i = 0; i < iECCLen; i++ ) + { + HB_TRACE( HB_TR_ALWAYS, ("ecc:%3d %02X", ( int )( unsigned char ) pECC[ i ], ( int )( unsigned char ) pECC[ i ]) ) ; + } +#endif + return pECC; +} + + +static void _qr_draw( PHB_BITBUFFER pBits, PHB_BITBUFFER pCWBits, int iVersion ) +{ + int i, j, no, up, right, iLength; + unsigned char *pi, *pj; + + HB_SYMBOL_UNUSED( pCWBits ); + + iLength = _qr_versionlength( iVersion ); + + /* draw position detection markers */ + for( i = 0; i < 7; i++ ) + { + hb_bitbuffer_set( pBits, i, 1 ); + hb_bitbuffer_set( pBits, i + 6 * iLength, 1 ); + hb_bitbuffer_set( pBits, i * iLength, 1 ); + hb_bitbuffer_set( pBits, i * iLength + 6, 1 ); + + hb_bitbuffer_set( pBits, i + ( iLength - 7 ) * iLength, 1 ); + hb_bitbuffer_set( pBits, i + ( iLength - 1 ) * iLength, 1 ); + hb_bitbuffer_set( pBits, ( iLength - 7 + i ) * iLength, 1 ); + hb_bitbuffer_set( pBits, ( iLength - 7 + i ) * iLength + 6, 1 ); + + hb_bitbuffer_set( pBits, iLength - 7 + i, 1 ); + hb_bitbuffer_set( pBits, iLength - 7 + i + 6 * iLength, 1 ); + hb_bitbuffer_set( pBits, iLength - 7 + i * iLength, 1 ); + hb_bitbuffer_set( pBits, iLength - 1 + i * iLength, 1 ); + } + for( i = 2; i < 5; i++ ) + { + for( j = 2; j < 5; j++ ) + { + hb_bitbuffer_set( pBits, i * iLength + j, 1 ); + hb_bitbuffer_set( pBits, i * iLength + j + iLength - 7, 1 ); + hb_bitbuffer_set( pBits, ( i + iLength - 7 ) * iLength + j, 1 ); + } + } + /* draw timing patterns */ + for( i = 8; i < iLength - 8; i += 2 ) + { + hb_bitbuffer_set( pBits, i + 6 * iLength, 1 ); + hb_bitbuffer_set( pBits, i * iLength + 6, 1 ); + } + /* draw alignment patterns */ + pi = s_align[ iVersion - 1 ]; + for( ; *pi; pi++ ) + { + pj = s_align[ iVersion - 1 ]; + for( ; *pj; pj++ ) + { + if( ( *pi > 10 && *pi < iLength - 10 ) || + ( *pj > 10 && *pj < iLength - 10 ) || + ( *pi > 10 && *pj > 10 )) + { + hb_bitbuffer_set( pBits, iLength * *pi + *pj - 1, 0 ); + hb_bitbuffer_set( pBits, iLength * *pi + *pj + 1, 0 ); + hb_bitbuffer_set( pBits, iLength * ( *pi - 1 ) + *pj, 0 ); + hb_bitbuffer_set( pBits, iLength * ( *pi + 1 ) + *pj, 0 ); + + hb_bitbuffer_set( pBits, iLength * *pi + *pj, 1 ); + hb_bitbuffer_set( pBits, iLength * ( *pi - 2 ) + *pj - 2, 1 ); + hb_bitbuffer_set( pBits, iLength * ( *pi - 2 ) + *pj - 1, 1 ); + hb_bitbuffer_set( pBits, iLength * ( *pi - 2 ) + *pj , 1 ); + hb_bitbuffer_set( pBits, iLength * ( *pi - 2 ) + *pj + 1, 1 ); + hb_bitbuffer_set( pBits, iLength * ( *pi - 2 ) + *pj + 2, 1 ); + hb_bitbuffer_set( pBits, ( *pi - 1 ) * iLength + *pj - 2, 1 ); + hb_bitbuffer_set( pBits, *pi * iLength + *pj - 2, 1 ); + hb_bitbuffer_set( pBits, ( *pi + 1 ) * iLength + *pj - 2, 1 ); + hb_bitbuffer_set( pBits, ( *pi - 1 ) * iLength + *pj + 2, 1 ); + hb_bitbuffer_set( pBits, *pi * iLength + *pj + 2, 1 ); + hb_bitbuffer_set( pBits, ( *pi + 1 ) * iLength + *pj + 2, 1 ); + hb_bitbuffer_set( pBits, iLength * ( *pi + 2 ) + *pj - 2, 1 ); + hb_bitbuffer_set( pBits, iLength * ( *pi + 2 ) + *pj - 1, 1 ); + hb_bitbuffer_set( pBits, iLength * ( *pi + 2 ) + *pj , 1 ); + hb_bitbuffer_set( pBits, iLength * ( *pi + 2 ) + *pj + 1, 1 ); + hb_bitbuffer_set( pBits, iLength * ( *pi + 2 ) + *pj + 2, 1 ); + } + } + } + + /* Dark module */ + hb_bitbuffer_set( pBits, 8 + iLength * ( iLength - 8 ), 1 ); + + + /* Draw data. Note: pCWBits == NULL is used only for debugging */ + if( pCWBits ) + { + i = j = iLength - 1; + right = 1; + up = 1; + no = 0; + while( i >= 0 && j >= 0 ) + { + if( ! _qr_fixed( iVersion, i, j ) ) + hb_bitbuffer_set( pBits, i * iLength + j, hb_bitbuffer_get( pCWBits, no++ ) ); + + if( right ) + { + j--; + } + else + { + if( up ) + { + if( i > 0 ) + { + i--; + j++; + } + else + { + up = 0; + j--; + } + } + else + { + if( i < iLength - 1 ) + { + i++; + j++; + } + else + { + up = 1; + j--; + } + } + } + right = ! right; + if( j == 6 ) + j--; + } + } +} + + +static int _qr_penalty( PHB_BITBUFFER pBits, int iVersion ) +{ + int i, j, k, iPenalty = 0, iLen = _qr_versionlength( iVersion ); + HB_BOOL bBitLast, bBit; + + /* 1. Same color modules in row/column */ + for( i = 0; i < iLen; i++ ) + { + /* Row */ + bBitLast = hb_bitbuffer_get( pBits, i * iLen ); + k = 1; + for( j = 1; j < iLen; j++ ) + { + bBit = hb_bitbuffer_get( pBits, i * iLen + j ); + if( bBit != bBitLast ) + { + if( k >= 5 ) + iPenalty += 3 + ( k - 5 ); + + bBitLast = bBit; + k = 1; + } + else + k++; + } + if( k >= 5 ) + iPenalty = 3 + ( k - 5 ); + + /* Col */ + bBitLast = hb_bitbuffer_get( pBits, i ); + k = 1; + for( j = 1; j < iLen; j++ ) + { + bBit = hb_bitbuffer_get( pBits, i + iLen * j ); + if( bBit != bBitLast ) + { + if( k >= 5 ) + iPenalty += 3 + ( k - 5 ); + + bBitLast = bBit; + k = 1; + } + else + k++; + } + if( k >= 5 ) + iPenalty = 3 + ( k - 5 ); + } + + /* 2. Block of same color modules */ + /* Instead of looking for non-overlapped MxN block, we can search for 2x2 overlapping blocks, */ + /* penalty value is the same for both of these methods */ + for( i = 0; i < iLen - 1; i++ ) + { + for( j = 0; j < iLen - 1; j++ ) + { + bBit = hb_bitbuffer_get( pBits, i * iLen + j ); + if( hb_bitbuffer_get( pBits, i * iLen + j + 1 ) == bBit && + hb_bitbuffer_get( pBits, ( i + 1 ) * iLen + j ) == bBit && + hb_bitbuffer_get( pBits, ( i + 1 ) * iLen + j + 1 ) == bBit ) + iPenalty += 3; + } + } + + /* 3. Black-White-Black-Black-Black-White-Black modules */ + for( i = 0; i < iLen - 6; i++ ) + { + for( j = 0; j < iLen - 6; j++ ) + { + if( hb_bitbuffer_get( pBits, i * iLen + j ) == HB_TRUE && + hb_bitbuffer_get( pBits, i * iLen + j + 1 ) == HB_FALSE && + hb_bitbuffer_get( pBits, i * iLen + j + 2 ) == HB_TRUE && + hb_bitbuffer_get( pBits, i * iLen + j + 3 ) == HB_TRUE && + hb_bitbuffer_get( pBits, i * iLen + j + 4 ) == HB_TRUE && + hb_bitbuffer_get( pBits, i * iLen + j + 5 ) == HB_FALSE && + hb_bitbuffer_get( pBits, i * iLen + j + 6 ) == HB_TRUE ) + iPenalty += 40; + + if( hb_bitbuffer_get( pBits, i * iLen + j ) == HB_TRUE && + hb_bitbuffer_get( pBits, ( i + 1 ) * iLen + j ) == HB_FALSE && + hb_bitbuffer_get( pBits, ( i + 2 ) * iLen + j ) == HB_TRUE && + hb_bitbuffer_get( pBits, ( i + 3 ) * iLen + j ) == HB_TRUE && + hb_bitbuffer_get( pBits, ( i + 4 ) * iLen + j ) == HB_TRUE && + hb_bitbuffer_get( pBits, ( i + 5 ) * iLen + j ) == HB_FALSE && + hb_bitbuffer_get( pBits, ( i + 6 ) * iLen + j ) == HB_TRUE ) + iPenalty += 40; + } + } + + /* 4. Proportion of color modules */ + k = 0; + for( i = 0; i < iLen; i++ ) + for( j = 0; j < iLen; j++ ) + if( hb_bitbuffer_get( pBits, i * iLen + j ) ) + k++; + k = k * 100 / ( iLen * iLen ); + if( k < 50 ) + k = 100 - k; + iPenalty += ( k / 5 ) * 10; + + return iPenalty; +} + + +static void _qr_mask_pattern( PHB_BITBUFFER pBits, int iVersion, int iMask ) +{ + int i, j, k, iLen = _qr_versionlength( iVersion ); + + for( i = 0; i < iLen; i++ ) + { + for( j = 0; j < iLen; j++ ) + { + if( ! _qr_fixed( iVersion, i, j ) ) + { + switch( iMask ) + { + case 0: + k = ( i + j ) % 2 == 0; + break; + case 1: + k = i % 2 == 0; + break; + case 2: + k = j % 3 == 0; + break; + case 3: + k = ( i + j ) % 3 == 0; + break; + case 4: + k = ( i / 2 + j / 3 ) % 2 == 0; + break; + case 5: + k = ( i * j ) % 2 + ( i * j ) % 3 == 0; + break; + case 6: + k = ( ( i * j ) % 2 + ( i * j ) % 3 ) % 2 == 0; + break; + case 7: + k = ( ( i * j ) % 3 + ( i + j ) % 2 ) % 2 == 0; + break; + } + if( k ) + hb_bitbuffer_not( pBits, i * iLen + j ); + } + } + } +} + + +static int _qr_mask( PHB_BITBUFFER pBits, int iVersion ) +{ + int i, iPenaltyMin = 0, iMaskMin, iPenalty; + + for( i = 0; i < 8; i++ ) + { + _qr_mask_pattern( pBits, iVersion, i ); + iPenalty = _qr_penalty( pBits, iVersion ); +#ifdef DEBUG_CODE + HB_TRACE( HB_TR_ALWAYS, ("mask:%d penalty:%d", i, iPenalty) ); +#endif + if( i == 0 || iPenalty < iPenaltyMin ) + { + iPenaltyMin = iPenalty; + iMaskMin = i; + } + _qr_mask_pattern( pBits, iVersion, i ); + } +#ifdef DEBUG_CODE + HB_TRACE( HB_TR_ALWAYS, ("mask:%d", iMaskMin) ); +// iMaskMin = 0; + HB_TRACE( HB_TR_ALWAYS, ("mask applied:%d", iMaskMin) ); +#endif + _qr_mask_pattern( pBits, iVersion, iMaskMin ); + return iMaskMin; +} + + +static void _qr_draw_version_format( PHB_BITBUFFER pBits, int iVersion, int iLevel, int iMask ) +{ + int i, iCRC, iLen = _qr_versionlength( iVersion ); + + if( iVersion >= 7 ) + { + iCRC = _qr_version_crc( iVersion ); + for( i = 0; i < 18; i++ ) + { + if( iCRC & ( 1 << 17 ) ) + { + hb_bitbuffer_set( pBits, iLen - 11 + ( i % 3 ) + iLen * ( i / 3 ), 1 ); + hb_bitbuffer_set( pBits, ( iLen - 11 + ( i % 3 ) ) * iLen + ( i / 3 ), 1 ); + } + iCRC <<= 1; + } + } + iCRC = _qr_format_crc( iLevel, iMask ); + for( i = 0; i < 15; i++ ) + { + if( iCRC & ( 1 << 14 ) ) + { + /* Top left */ + if( i <= 7 ) + hb_bitbuffer_set( pBits, ( i + ( i >= 6 ? 1 : 0 ) ) * iLen + 8, 1 ); + else + hb_bitbuffer_set( pBits, ( 14 - i ) + ( i == 8 ? 1 : 0 ) + iLen * 8, 1 ); + + /* Top right and bottom left */ + if( i <= 7 ) + hb_bitbuffer_set( pBits, iLen - 1 - i + iLen * 8, 1 ); + else + hb_bitbuffer_set( pBits, ( iLen - 15 + i ) * iLen + 8, 1 ); + } + iCRC <<= 1; + } + +#if 0 + /* _qr_fixed() test code */ + for( i = 0; i < iLen; i++ ) + { + int j; + for( j = 0; j < iLen; j++ ) + hb_bitbuffer_set( pBits, i * iLen + j, _qr_fixed( iVersion, i, j ) ); + } +#endif +} + + +PHB_ZEBRA hb_zebra_create_qrcode( const char * szCode, HB_SIZE nLen, int iFlags ) +{ + PHB_ZEBRA pZebra; + PHB_BITBUFFER pData, pFinal; + unsigned char * pECC; + int iVersion, iLevel, iMask; + + pZebra = hb_zebra_create(); + pZebra->iType = HB_ZEBRA_TYPE_QRCODE; + + if( nLen > 7089 ) + { + pZebra->iError = HB_ZEBRA_ERROR_TOOLARGE; + return pZebra; + } + + switch( iFlags & HB_ZEBRA_FLAG_QR_LEVEL_MASK ) + { + case HB_ZEBRA_FLAG_QR_LEVEL_M: + iLevel = 1; + break; + case HB_ZEBRA_FLAG_QR_LEVEL_Q: + iLevel = 2; + break; + case HB_ZEBRA_FLAG_QR_LEVEL_H: + iLevel = 3; + break; + default: + iLevel = 0; + break; + } + +#ifdef DEBUG_CODE + HB_TRACE( HB_TR_ALWAYS, ("qr1 iLevel:%d", iLevel) ); +#endif + + pData = hb_bitbuffer_create(); + iVersion = _qr_dataencode( szCode, nLen, pData, iLevel ); + +#ifdef DEBUG_CODE + HB_TRACE( HB_TR_ALWAYS, ("qr3 iVersion:%d", iVersion) ); +#endif + + if( iVersion == 0 ) + { + hb_bitbuffer_destroy( pData ); + pZebra->iError = HB_ZEBRA_ERROR_TOOLARGE; + return pZebra; + } + + pZebra->iCol = _qr_versionlength( iVersion ); + + pZebra->szCode = hb_strdup( szCode ); + + pECC = _qr_checksum( pData, iVersion, iLevel ); + + pFinal = _qr_interlace( pData, pECC, iVersion, iLevel ); + hb_bitbuffer_destroy( pData ); + hb_xfree( pECC ); + + pZebra->pBits = hb_bitbuffer_create(); + _qr_draw( pZebra->pBits, pFinal, iVersion ); + hb_bitbuffer_destroy( pFinal ); + + iMask = _qr_mask( pZebra->pBits, iVersion ); + + _qr_draw_version_format(pZebra->pBits, iVersion, iLevel, iMask ); + return pZebra; +} + + +HB_FUNC( HB_ZEBRA_CREATE_QRCODE ) +{ + PHB_ITEM pItem = hb_param( 1, HB_IT_STRING ); + if( pItem ) + { + hb_zebra_ret( hb_zebra_create_qrcode( 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/tests/testcair.prg b/harbour/contrib/hbzebra/tests/testcair.prg index 85d6a8fb13..2d911da0de 100644 --- a/harbour/contrib/hbzebra/tests/testcair.prg +++ b/harbour/contrib/hbzebra/tests/testcair.prg @@ -37,11 +37,11 @@ PROCEDURE main() 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, 420, 1, "CODE128", "61300073570004616") 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 :)") - + DrawBarcode( hCairo, 580, 1, "QRCODE", "http://harbour-project.org/" ) cairo_destroy( hCairo ) cairo_surface_write_to_png( hSurface, "testcair.png" ) cairo_surface_destroy( hSurface ) @@ -49,7 +49,7 @@ PROCEDURE main() PROCEDURE DrawBarcode( hCairo, nY, nLineWidth, cType, cCode, nFlags ) - LOCAL hZebra, nLineHeight + LOCAL hZebra, nLineHeight, cTxt SWITCH cType CASE "EAN13" ; hZebra := hb_zebra_create_ean13( cCode, nFlags ) ; EXIT @@ -65,6 +65,7 @@ PROCEDURE DrawBarcode( hCairo, nY, nLineWidth, cType, cCode, nFlags ) CASE "CODE128" ; hZebra := hb_zebra_create_code128( cCode, nFlags ) ; EXIT CASE "PDF417" ; hZebra := hb_zebra_create_pdf417( cCode, nFlags ); nLineHeight := nLineWidth * 3 ; EXIT CASE "DATAMATRIX" ; hZebra := hb_zebra_create_datamatrix( cCode, nFlags ); nLineHeight := nLineWidth ; EXIT + CASE "QRCODE" ; hZebra := hb_zebra_create_qrcode( cCode, nFlags ); nLineHeight := nLineWidth ; EXIT ENDSWITCH IF hZebra != NIL IF hb_zebra_geterror( hZebra ) == 0 @@ -73,8 +74,10 @@ PROCEDURE DrawBarcode( hCairo, nY, nLineWidth, cType, cCode, nFlags ) ENDIF cairo_move_to( hCairo, 40, nY + 13 ) cairo_show_text( hCairo, cType ) - cairo_move_to( hCairo, 100, nY + 13 ) - cairo_show_text( hCairo, hb_zebra_getcode( hZebra ) ) + IF LEN( cTxt := hb_zebra_getcode( hZebra ) ) < 20 + cairo_move_to( hCairo, 100, nY + 13 ) + cairo_show_text( hCairo, cTxt ) + ENDIF hb_zebra_draw_cairo( hZebra, hCairo, 220, nY, nLineWidth, nLineHeight ) ELSE ? "Type", cType, "Code", cCode, "Error", hb_zebra_geterror( hZebra ) @@ -92,7 +95,8 @@ STATIC FUNCTION hb_zebra_draw_cairo( hZebra, hCairo, ... ) ENDIF cairo_save( hCairo ) - hb_zebra_draw( hZebra, {| x, y, w, h | cairo_rectangle( hCairo, x, y, w, h ), cairo_fill( hCairo ) }, ... ) + hb_zebra_draw( hZebra, {| x, y, w, h | cairo_rectangle( hCairo, x, y, w, h ) }, ... ) + cairo_fill( hCairo ) cairo_restore( hCairo ) RETURN 0 diff --git a/harbour/contrib/hbzebra/tests/testhpdf.prg b/harbour/contrib/hbzebra/tests/testhpdf.prg index 88353b2daf..16b2ac3d08 100644 --- a/harbour/contrib/hbzebra/tests/testhpdf.prg +++ b/harbour/contrib/hbzebra/tests/testhpdf.prg @@ -46,6 +46,7 @@ PROCEDURE Main() DrawBarcode( page, 440, 1, "CODE128", "Wikipedia") DrawBarcode( page, 460, 1, "PDF417", "Hello, World of Harbour!!! It's 2D barcode PDF417 :)" ) DrawBarcode( page, 540, 1, "DATAMATRIX", "Hello, World of Harbour!!! It's 2D barcode DataMatrix :)") + DrawBarcode( page, 580, 1, "QRCODE", "http://harbour-project.org/" ) FErase( "testhpdf.pdf" ) ? HPDF_SaveToFile( pdf, "testhpdf.pdf" ) @@ -53,7 +54,7 @@ PROCEDURE Main() RETURN PROCEDURE DrawBarcode( page, nY, nLineWidth, cType, cCode, nFlags ) - LOCAL hZebra, nLineHeight + LOCAL hZebra, nLineHeight, cTxt nY := HPDF_Page_GetHeight( page ) - nY @@ -71,6 +72,7 @@ PROCEDURE DrawBarcode( page, nY, nLineWidth, cType, cCode, nFlags ) CASE "CODE128" ; hZebra := hb_zebra_create_code128( cCode, nFlags ) ; EXIT CASE "PDF417" ; hZebra := hb_zebra_create_pdf417( cCode, nFlags ); nLineHeight := nLineWidth * 3 ; EXIT CASE "DATAMATRIX" ; hZebra := hb_zebra_create_datamatrix( cCode, nFlags ); nLineHeight := nLineWidth ; EXIT + CASE "QRCODE" ; hZebra := hb_zebra_create_qrcode( cCode, nFlags ); nLineHeight := nLineWidth ; EXIT ENDSWITCH IF hZebra != NIL @@ -80,7 +82,10 @@ PROCEDURE DrawBarcode( page, nY, nLineWidth, cType, cCode, nFlags ) ENDIF HPDF_Page_BeginText( page ) HPDF_Page_TextOut( page, 40, nY - 13, cType ) - HPDF_Page_TextOut( page, 150, nY - 13, hb_zebra_getcode( hZebra ) ) + cTxt := hb_zebra_getcode( hZebra ) + IF LEN( cTxt ) < 20 + HPDF_Page_TextOut( page, 150, nY - 13, cTxt ) + ENDIF HPDF_Page_EndText( page ) hb_zebra_draw_hpdf( hZebra, page, 300, nY, nLineWidth, -nLineHeight ) ELSE diff --git a/harbour/contrib/hbzebra/tests/testwin.prg b/harbour/contrib/hbzebra/tests/testwin.prg index 42b3b5b397..c26b606718 100644 --- a/harbour/contrib/hbzebra/tests/testwin.prg +++ b/harbour/contrib/hbzebra/tests/testwin.prg @@ -74,6 +74,7 @@ PROCEDURE Main() DrawBarcode( hDC, 440, 1, "CODE128", "Wikipedia") DrawBarcode( hDC, 460, 1, "PDF417", "Hello, World of Harbour!!! It's 2D barcode PDF417 :)" ) DrawBarcode( hDC, 540, 1, "DATAMATRIX", "Hello, World of Harbour!!! It's 2D barcode DataMatrix :)") + DrawBarcode( hDC, 580, 1, "QRCODE", "http://harbour-project.org/" ) wapi_EndPage( hDC ) ENDIF @@ -86,7 +87,7 @@ PROCEDURE Main() #define _SCALE_ 7.2 PROCEDURE DrawBarcode( hDC, nY, nLineWidth, cType, cCode, nFlags ) - LOCAL hZebra, nLineHeight + LOCAL hZebra, nLineHeight, cTxt SWITCH cType CASE "EAN13" ; hZebra := hb_zebra_create_ean13( cCode, nFlags ) ; EXIT @@ -102,6 +103,7 @@ PROCEDURE DrawBarcode( hDC, nY, nLineWidth, cType, cCode, nFlags ) CASE "CODE128" ; hZebra := hb_zebra_create_code128( cCode, nFlags ) ; EXIT CASE "PDF417" ; hZebra := hb_zebra_create_pdf417( cCode, nFlags ); nLineHeight := nLineWidth * 3 ; EXIT CASE "DATAMATRIX" ; hZebra := hb_zebra_create_datamatrix( cCode, nFlags ); nLineHeight := nLineWidth ; EXIT + CASE "QRCODE" ; hZebra := hb_zebra_create_qrcode( cCode, nFlags ); nLineHeight := nLineWidth ; EXIT ENDSWITCH nY *= _SCALE_ @@ -113,7 +115,9 @@ PROCEDURE DrawBarcode( hDC, nY, nLineWidth, cType, cCode, nFlags ) nLineHeight := 16 ENDIF wapi_TextOut( hDC, 40 * _SCALE_, nY, cType ) - wapi_TextOut( hDC, 150 * _SCALE_, nY, hb_zebra_getcode( hZebra ) ) + IF LEN( cTxt := hb_zebra_getcode( hZebra ) ) < 20 + wapi_TextOut( hDC, 150 * _SCALE_, nY, cTxt ) + ENDIF hb_zebra_draw_wapi( hZebra, hDC, wapi_CreateSolidBrush( 0 ), 300 * _SCALE_, nY, nLineWidth, nLineHeight * _SCALE_ ) ELSE ? "Type", cType, "Code", cCode, "Error", hb_zebra_geterror( hZebra )