2008-07-14 01:15:55 +04:00
/* common.c - Contains functions needed for a number of barcodes */
/*
libzint - the open source barcode library
2023-06-12 03:25:55 +03:00
Copyright ( C ) 2008 - 2023 Robin Stuart < rstuart114 @ gmail . com >
2008-07-14 01:15:55 +04:00
2013-05-16 21:26:38 +04:00
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
2008-07-14 01:15:55 +04:00
2016-02-20 12:38:03 +03:00
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2013-05-16 21:26:38 +04:00
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
2016-02-20 12:38:03 +03:00
documentation and / or other materials provided with the distribution .
2013-05-16 21:26:38 +04:00
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
2016-02-20 12:38:03 +03:00
without specific prior written permission .
2008-07-14 01:15:55 +04:00
2013-05-16 21:26:38 +04:00
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS " AND
ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY
2016-02-20 12:38:03 +03:00
OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
2013-05-16 21:26:38 +04:00
SUCH DAMAGE .
2016-02-20 12:38:03 +03:00
*/
2022-06-24 16:38:48 +03:00
/* SPDX-License-Identifier: BSD-3-Clause */
2021-11-11 16:30:58 +03:00
# include <assert.h>
2008-07-14 01:15:55 +04:00
# include <stdio.h>
# include "common.h"
2020-12-19 20:13:35 +03:00
/* Converts a character 0-9, A-F to its equivalent integer value */
2019-12-19 03:37:55 +03:00
INTERNAL int ctoi ( const char source ) {
2022-06-24 16:38:48 +03:00
if ( z_isdigit ( source ) )
2016-02-20 12:38:03 +03:00
return ( source - ' 0 ' ) ;
2017-10-21 14:45:50 +03:00
if ( ( source > = ' A ' ) & & ( source < = ' F ' ) )
return ( source - ' A ' + 10 ) ;
if ( ( source > = ' a ' ) & & ( source < = ' f ' ) )
return ( source - ' a ' + 10 ) ;
return - 1 ;
2008-07-14 01:15:55 +04:00
}
2020-12-19 20:13:35 +03:00
/* Converts an integer value to its hexadecimal character */
INTERNAL char itoc ( const int source ) {
if ( ( source > = 0 ) & & ( source < = 9 ) ) {
return ( ' 0 ' + source ) ;
}
2022-11-07 01:25:19 +03:00
return ( ' A ' - 10 + source ) ;
2019-12-04 16:45:01 +03:00
}
2020-12-19 20:13:35 +03:00
/* Converts decimal string of length <= 9 to integer value. Returns -1 if not numeric */
INTERNAL int to_int ( const unsigned char source [ ] , const int length ) {
int val = 0 ;
2023-06-12 03:25:55 +03:00
int non_digit = 0 ;
2017-05-14 10:15:08 +03:00
int i ;
2017-10-23 22:37:52 +03:00
2017-05-14 10:15:08 +03:00
for ( i = 0 ; i < length ; i + + ) {
2020-12-19 20:13:35 +03:00
val * = 10 ;
val + = source [ i ] - ' 0 ' ;
2023-06-12 03:25:55 +03:00
non_digit | = ! z_isdigit ( source [ i ] ) ;
2017-05-14 10:15:08 +03:00
}
2023-06-12 03:25:55 +03:00
return non_digit ? - 1 : val ;
2017-07-21 16:16:23 +03:00
}
2019-12-19 03:37:55 +03:00
2022-11-07 01:25:19 +03:00
/* Converts lower case characters to upper case in string `source` */
2021-10-21 01:05:30 +03:00
INTERNAL void to_upper ( unsigned char source [ ] , const int length ) {
int i ;
2008-07-14 01:15:55 +04:00
2021-10-21 01:05:30 +03:00
for ( i = 0 ; i < length ; i + + ) {
2023-06-12 03:25:55 +03:00
source [ i ] & = z_islower ( source [ i ] ) ? 0x5F : 0xFF ;
2016-02-20 12:38:03 +03:00
}
2008-07-14 01:15:55 +04:00
}
2022-11-07 01:25:19 +03:00
/* Returns the number of times a character occurs in `source` */
INTERNAL int chr_cnt ( const unsigned char source [ ] , const int length , const unsigned char c ) {
2021-01-11 21:11:41 +03:00
int count = 0 ;
int i ;
for ( i = 0 ; i < length ; i + + ) {
2023-06-12 03:25:55 +03:00
count + = source [ i ] = = c ;
2021-01-11 21:11:41 +03:00
}
return count ;
}
Add multiple segments support for AZTEC, CODEONE, DATAMATRIX, DOTCODE,
GRIDMATRIX, HANXIN, MAXICODE, MICROPDF417, PDF417, QRCODE, RMQR, ULTRA
RMQR: fix ECI encoding (wrong bit length for indicator)
MICROQR: check versions M1 and M2 for allowed characters so as to give
better error messages
DOTCODE: some small optimizations
common.c: add is_chr(), segs_length(), segs_cpy()
CODEONE/CODE128/DOTCODE/GRIDMATRIX/HANXIN/MAXICODE/QRCODE/ULTRA: add
namespace prefixes to static funcs/data
includes: use Z_ prefix, unuse double underscore prefixes (guard defines)
manual.txt: compress some tables using double/treble column sets
2022-05-09 21:50:50 +03:00
/* Flag table for `is_chr()` and `is_sane()` */
# define IS_CLS_F (IS_CLI_F | IS_SIL_F)
static const unsigned short flgs [ 256 ] = {
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /*00-1F*/
IS_SPC_F , IS_C82_F , IS_C82_F , IS_HSH_F , /*20-23*/ /* !"# */
IS_CLS_F , IS_SIL_F | IS_C82_F , IS_C82_F , IS_C82_F , /*24-27*/ /* $%&' */
IS_C82_F , IS_C82_F , IS_AST_F , IS_PLS_F , /*28-2B*/ /* ()*+ */
IS_C82_F , IS_MNS_F , IS_CLS_F | IS_C82_F , IS_CLS_F | IS_C82_F , /*2B-2F*/ /* ,-./ */
IS_NUM_F , IS_NUM_F , IS_NUM_F , IS_NUM_F , /*30-33*/ /* 0123 */
IS_NUM_F , IS_NUM_F , IS_NUM_F , IS_NUM_F , /*34-37*/ /* 4567 */
IS_NUM_F , IS_NUM_F , IS_CLI_F | IS_C82_F , IS_C82_F , /*38-3B*/ /* 89:; */
IS_C82_F , IS_C82_F , IS_C82_F , IS_C82_F , /*3B-3F*/ /* <=>? */
0 , IS_UHX_F | IS_ARS_F , IS_UHX_F | IS_ARS_F , IS_UHX_F | IS_ARS_F , /*40-43*/ /* @ABC */
IS_UHX_F | IS_ARS_F , IS_UHX_F | IS_ARS_F , IS_UHX_F | IS_ARS_F , IS_UPO_F | IS_ARS_F , /*44-47*/ /* DEFG */
IS_UPO_F | IS_ARS_F , IS_UPO_F , IS_UPO_F | IS_ARS_F , IS_UPO_F | IS_ARS_F , /*48-4B*/ /* HIJK */
IS_UPO_F | IS_ARS_F , IS_UPO_F | IS_ARS_F , IS_UPO_F | IS_ARS_F , IS_UPO_F , /*4B-4F*/ /* LMNO */
IS_UPO_F | IS_ARS_F , IS_UPO_F , IS_UPO_F | IS_ARS_F , IS_UPO_F | IS_ARS_F , /*50-53*/ /* PQRS */
IS_UPO_F | IS_ARS_F , IS_UPO_F | IS_ARS_F , IS_UPO_F | IS_ARS_F , IS_UPO_F | IS_ARS_F , /*53-57*/ /* TUVW */
IS_UX__F | IS_ARS_F , IS_UPO_F | IS_ARS_F , IS_UPO_F | IS_ARS_F , 0 , /*58-5B*/ /* XYZ[ */
0 , 0 , 0 , IS_C82_F , /*5B-5F*/ /* \]^_ */
0 , IS_LHX_F , IS_LHX_F , IS_LHX_F , /*60-63*/ /* `abc */
IS_LHX_F , IS_LHX_F , IS_LHX_F , IS_LWO_F , /*64-67*/ /* defg */
IS_LWO_F , IS_LWO_F , IS_LWO_F , IS_LWO_F , /*68-6B*/ /* hijk */
IS_LWO_F , IS_LWO_F , IS_LWO_F , IS_LWO_F , /*6B-6F*/ /* lmno */
IS_LWO_F , IS_LWO_F , IS_LWO_F , IS_LWO_F , /*70-73*/ /* pqrs */
IS_LWO_F , IS_LWO_F , IS_LWO_F , IS_LWO_F , /*74-77*/ /* tuvw */
IS_LX__F , IS_LWO_F , IS_LWO_F , 0 , /*78-7B*/ /* xyz{ */
0 , 0 , 0 , 0 , /*7B-7F*/ /* |}~D */
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /*80-9F*/
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /*A0-BF*/
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /*C0-DF*/
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /*E0-FF*/
} ;
/* Whether a character matches `flg` */
INTERNAL int is_chr ( const unsigned int flg , const unsigned int c ) {
return c < 0x80 & & ( flgs [ c ] & flg ) ! = 0 ;
}
2016-02-20 12:38:03 +03:00
/* Verifies that a string only uses valid characters */
2021-10-21 01:05:30 +03:00
INTERNAL int is_sane ( const unsigned int flg , const unsigned char source [ ] , const int length ) {
int i ;
2016-02-20 12:38:03 +03:00
for ( i = 0 ; i < length ; i + + ) {
2021-10-21 01:05:30 +03:00
if ( ! ( flgs [ source [ i ] ] & flg ) ) {
return 0 ;
2016-02-20 12:38:03 +03:00
}
}
2021-10-21 01:05:30 +03:00
return 1 ;
2008-07-14 01:15:55 +04:00
}
2017-05-29 12:43:47 +03:00
/* Replaces huge switch statements for looking up in tables */
2021-10-21 01:05:30 +03:00
/* Verifies that a string only uses valid characters, and returns `test_string` position of each in `posns` array */
INTERNAL int is_sane_lookup ( const char test_string [ ] , const int test_length , const unsigned char source [ ] ,
const int length , int * posns ) {
int i , j ;
2008-07-14 01:15:55 +04:00
2021-10-21 01:05:30 +03:00
for ( i = 0 ; i < length ; i + + ) {
posns [ i ] = - 1 ;
for ( j = 0 ; j < test_length ; j + + ) {
if ( source [ i ] = = test_string [ j ] ) {
posns [ i ] = j ;
break ;
}
}
if ( posns [ i ] = = - 1 ) {
return 0 ;
2016-02-20 12:38:03 +03:00
}
}
2021-10-21 01:05:30 +03:00
return 1 ;
2008-07-14 01:15:55 +04:00
}
2022-11-07 01:25:19 +03:00
/* Returns the position of `data` in `set_string` */
2021-09-27 01:55:16 +03:00
INTERNAL int posn ( const char set_string [ ] , const char data ) {
2021-10-21 01:05:30 +03:00
const char * s ;
2021-09-27 01:55:16 +03:00
2021-10-21 01:05:30 +03:00
for ( s = set_string ; * s ; s + + ) {
if ( data = = * s ) {
return s - set_string ;
2021-09-27 01:55:16 +03:00
}
}
return - 1 ;
}
2022-11-07 01:25:19 +03:00
/* Converts `arg` to a string representing its binary equivalent of length `length` and places in `binary` at
` bin_posn ` . Returns ` bin_posn ` + ` length ` */
2020-12-19 20:13:35 +03:00
INTERNAL int bin_append_posn ( const int arg , const int length , char * binary , const int bin_posn ) {
int i ;
2023-06-12 03:25:55 +03:00
const int end = length - 1 ;
2020-12-19 20:13:35 +03:00
for ( i = 0 ; i < length ; i + + ) {
2023-06-12 03:25:55 +03:00
binary [ bin_posn + i ] = ' 0 ' + ( ( arg > > ( end - i ) ) & 1 ) ;
2020-12-19 20:13:35 +03:00
}
return bin_posn + length ;
}
Add multiple segments support for AZTEC, CODEONE, DATAMATRIX, DOTCODE,
GRIDMATRIX, HANXIN, MAXICODE, MICROPDF417, PDF417, QRCODE, RMQR, ULTRA
RMQR: fix ECI encoding (wrong bit length for indicator)
MICROQR: check versions M1 and M2 for allowed characters so as to give
better error messages
DOTCODE: some small optimizations
common.c: add is_chr(), segs_length(), segs_cpy()
CODEONE/CODE128/DOTCODE/GRIDMATRIX/HANXIN/MAXICODE/QRCODE/ULTRA: add
namespace prefixes to static funcs/data
includes: use Z_ prefix, unuse double underscore prefixes (guard defines)
manual.txt: compress some tables using double/treble column sets
2022-05-09 21:50:50 +03:00
# ifndef Z_COMMON_INLINE
2022-11-07 01:25:19 +03:00
/* Returns true (1) if a module is dark/black, otherwise false (0) */
2019-12-19 03:37:55 +03:00
INTERNAL int module_is_set ( const struct zint_symbol * symbol , const int y_coord , const int x_coord ) {
2020-11-01 21:32:55 +03:00
return ( symbol - > encoded_data [ y_coord ] [ x_coord > > 3 ] > > ( x_coord & 0x07 ) ) & 1 ;
2009-06-01 00:33:54 +04:00
}
2022-11-07 01:25:19 +03:00
/* Sets a module to dark/black */
2019-12-19 03:37:55 +03:00
INTERNAL void set_module ( struct zint_symbol * symbol , const int y_coord , const int x_coord ) {
2020-11-01 21:32:55 +03:00
symbol - > encoded_data [ y_coord ] [ x_coord > > 3 ] | = 1 < < ( x_coord & 0x07 ) ;
}
2022-11-07 01:25:19 +03:00
/* Returns true (1-8) if a module is colour, otherwise false (0) */
2020-11-01 21:32:55 +03:00
INTERNAL int module_colour_is_set ( const struct zint_symbol * symbol , const int y_coord , const int x_coord ) {
return symbol - > encoded_data [ y_coord ] [ x_coord ] ;
2020-06-04 20:45:25 +03:00
}
2022-11-07 01:25:19 +03:00
/* Sets a module to a colour */
2020-06-04 20:45:25 +03:00
INTERNAL void set_module_colour ( struct zint_symbol * symbol , const int y_coord , const int x_coord , const int colour ) {
symbol - > encoded_data [ y_coord ] [ x_coord ] = colour ;
2009-06-01 00:33:54 +04:00
}
2020-11-01 21:32:55 +03:00
# endif
2009-06-01 00:33:54 +04:00
2022-11-07 01:25:19 +03:00
/* Sets a dark/black module to white (i.e. unsets) */
2019-12-19 03:37:55 +03:00
INTERNAL void unset_module ( struct zint_symbol * symbol , const int y_coord , const int x_coord ) {
2020-11-01 21:32:55 +03:00
symbol - > encoded_data [ y_coord ] [ x_coord > > 3 ] & = ~ ( 1 < < ( x_coord & 0x07 ) ) ;
2009-06-01 00:33:54 +04:00
}
2016-02-20 12:38:03 +03:00
/* Expands from a width pattern to a bit pattern */
2021-10-21 01:05:30 +03:00
INTERNAL void expand ( struct zint_symbol * symbol , const char data [ ] , const int length ) {
2016-02-20 12:38:03 +03:00
2021-10-21 01:05:30 +03:00
int reader ;
2016-02-20 12:38:03 +03:00
int writer , i ;
2020-10-26 15:21:43 +03:00
int latch , num ;
2021-10-31 00:00:31 +03:00
const int row = symbol - > rows ;
2021-10-21 01:05:30 +03:00
symbol - > rows + + ;
2016-02-20 12:38:03 +03:00
writer = 0 ;
2020-10-26 15:21:43 +03:00
latch = 1 ;
2016-02-20 12:38:03 +03:00
2021-10-21 01:05:30 +03:00
for ( reader = 0 ; reader < length ; reader + + ) {
2020-10-26 15:21:43 +03:00
num = ctoi ( data [ reader ] ) ;
2021-11-11 16:30:58 +03:00
assert ( num > = 0 ) ;
2020-10-26 15:21:43 +03:00
for ( i = 0 ; i < num ; i + + ) {
if ( latch ) {
2021-10-21 01:05:30 +03:00
set_module ( symbol , row , writer ) ;
2016-02-20 12:38:03 +03:00
}
writer + + ;
}
2020-10-26 15:21:43 +03:00
latch = ! latch ;
2016-02-20 12:38:03 +03:00
}
2021-10-21 01:05:30 +03:00
if ( writer > symbol - > width ) {
symbol - > width = writer ;
2016-02-20 12:38:03 +03:00
}
2008-07-14 01:15:55 +04:00
}
2008-12-25 00:29:31 +03:00
2022-11-07 01:25:19 +03:00
/* Whether `symbology` can have row binding */
2019-12-19 03:37:55 +03:00
INTERNAL int is_stackable ( const int symbology ) {
2020-09-30 14:19:12 +03:00
if ( symbology < BARCODE_PHARMA_TWO & & symbology ! = BARCODE_POSTNET ) {
2017-05-29 12:43:47 +03:00
return 1 ;
2016-09-04 13:04:41 +03:00
}
2017-10-23 22:37:52 +03:00
2016-09-04 13:04:41 +03:00
switch ( symbology ) {
- API: add new zint_symbol `dpmm` field for output resolution (BMP/
EMF/PCX/PNG/TIF only, i.e. excluding EPS, GIF & SVG)
- Add support for specifying scale by X-dimension and resolution
with new option `--scalexdimdp` for CLI/Tcl & new API function
`ZBarcode_Scale_From_XdimDp()` (+ `ZBarcode_XdimDp_From_Scale()`
& `ZBarcode_Default_Xdim()`) and new GUI popup; manual: document
- BMP/EMF/PCX/PNG/TIF: use new `dpmm` resolution field (for EMF
following Inkscape)
- backend_qt: add `dpmm()`, `vectorWidth()`, `vectorHeight()`,
`noPng()`, `getVersion()`, `takesGS1AIData()`, & `XdimDp` stuff
incl. new `QZintXdimDp` struct for passing around scale vars &
use in `getAsCLI()`; add comments
- Raise `scale` limit to 200 (from 100) to allow for large dpmm
- output: create directories & subdirectories as necessary for
output path using new function `out_fopen()` and use in BMP/EMF/
EPS/GIF/PCX/PNG/SVG/TIF
- DPLEIT/DPIDENT: format HRT according to (incomplete)
documentation, and set default height to 72X (from 50X)
- CODE128B renamed to CODE128AB as can use subsets A and/or B
- CODABAR: fix minimum height calc
- EMF: fix indexing of handles (zero-based not 1-based)
- GUI: fix symbology zap (previous technique of clearing and
re-loading settings without doing a sync no longer works);
fix UPCEAN guard descent enable
- MAILMARK: better error message if input < 14 characters
- GUI: add "Default" button for DAFT tracker ratio & enable/disable
various default buttons; use new `takesGS1AIData()` to
enable/disable GS1-specific checkboxes
- CLI: use new `validate_float()` to parse float options (7
significant digits allowed only, no scientific notation)
- DATAMATRIX/GRIDMATRIX/PDF417/QR/ULTRA: micro-optimize structapp
ID parse
- library/CLI: fiddle with static asserts (make CHAR_BIT sensitive,
supposedly)
- win32/README: update building libpng (assembly removed)
- README.linux: document incompatibility of Qt6 >= 6.3
- manual: expand Barcode Studio waffle
- test suite: change range separator to hyphen and allow multiple
excludes
2022-12-03 00:39:01 +03:00
case BARCODE_CODE128AB :
2016-09-04 13:04:41 +03:00
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 :
2016-09-12 23:47:40 +03:00
case BARCODE_CODABLOCKF :
2020-05-16 12:22:33 +03:00
case BARCODE_HIBC_BLOCKF :
2017-05-29 12:43:47 +03:00
return 1 ;
2020-12-19 20:13:35 +03:00
break ;
2016-09-04 13:04:41 +03:00
}
2017-05-29 12:43:47 +03:00
return 0 ;
2008-12-25 00:29:31 +03:00
}
2023-11-19 22:39:54 +03:00
/* Whether `symbology` is EAN/UPC */
INTERNAL int is_upcean ( const int symbology ) {
2020-07-15 21:00:12 +03:00
switch ( symbology ) {
case BARCODE_EANX :
case BARCODE_EANX_CHK :
case BARCODE_UPCA :
case BARCODE_UPCA_CHK :
case BARCODE_UPCE :
case BARCODE_UPCE_CHK :
case BARCODE_ISBNX :
case BARCODE_EANX_CC :
case BARCODE_UPCA_CC :
case BARCODE_UPCE_CC :
return 1 ;
2020-12-19 20:13:35 +03:00
break ;
2016-02-20 12:38:03 +03:00
}
return 0 ;
2009-06-18 14:20:23 +04:00
}
2022-11-07 01:25:19 +03:00
/* Whether `symbology` can have composite 2D component data */
2020-08-05 17:58:21 +03:00
INTERNAL int is_composite ( const int symbology ) {
2020-07-29 22:43:08 +03:00
return symbology > = BARCODE_EANX_CC & & symbology < = BARCODE_DBAR_EXPSTK_CC ;
2019-10-17 12:06:21 +03:00
}
2022-11-07 01:25:19 +03:00
/* Whether `symbology` is a matrix design renderable as dots */
2022-01-01 18:24:59 +03:00
INTERNAL int is_dotty ( const int symbology ) {
switch ( symbology ) {
/* Note MAXICODE and ULTRA absent */
case BARCODE_QRCODE :
case BARCODE_DATAMATRIX :
case BARCODE_MICROQR :
case BARCODE_HIBC_DM :
case BARCODE_AZTEC :
case BARCODE_HIBC_QR :
case BARCODE_HIBC_AZTEC :
case BARCODE_AZRUNE :
case BARCODE_CODEONE :
case BARCODE_GRIDMATRIX :
case BARCODE_HANXIN :
2022-12-08 16:48:31 +03:00
case BARCODE_MAILMARK_2D :
2022-01-01 18:24:59 +03:00
case BARCODE_DOTCODE :
case BARCODE_UPNQR :
case BARCODE_RMQR :
return 1 ;
break ;
}
return 0 ;
}
2022-11-07 01:25:19 +03:00
/* Whether `symbology` has a fixed aspect ratio (matrix design) */
2022-01-01 18:24:59 +03:00
INTERNAL int is_fixed_ratio ( const int symbology ) {
if ( is_dotty ( symbology ) ) {
return 1 ;
}
switch ( symbology ) {
case BARCODE_MAXICODE :
case BARCODE_ULTRA :
return 1 ;
break ;
}
return 0 ;
}
2020-12-19 20:13:35 +03:00
/* Whether next two characters are digits */
2021-10-21 01:05:30 +03:00
INTERNAL int is_twodigits ( const unsigned char source [ ] , const int length , const int position ) {
2022-06-24 16:38:48 +03:00
if ( ( position + 1 < length ) & & z_isdigit ( source [ position ] ) & & z_isdigit ( source [ position + 1 ] ) ) {
2020-06-04 20:45:25 +03:00
return 1 ;
2016-02-20 12:38:03 +03:00
}
2012-12-31 17:41:59 +04:00
2016-02-20 12:38:03 +03:00
return 0 ;
2009-07-05 00:48:42 +04:00
}
2022-11-07 01:25:19 +03:00
/* Returns how many consecutive digits lie immediately ahead up to `max`, or all if `max` is -1 */
INTERNAL int cnt_digits ( const unsigned char source [ ] , const int length , const int position , const int max ) {
int i ;
const int max_length = max = = - 1 | | position + max > length ? length : position + max ;
for ( i = position ; i < max_length & & z_isdigit ( source [ i ] ) ; i + + ) ;
return i - position ;
}
2019-11-27 19:16:14 +03:00
/* State machine to decode UTF-8 to Unicode codepoints (state 0 means done, state 12 means error) */
2020-07-10 21:39:32 +03:00
INTERNAL unsigned int decode_utf8 ( unsigned int * state , unsigned int * codep , const unsigned char byte ) {
2019-11-27 19:16:14 +03:00
/*
Copyright ( c ) 2008 - 2009 Bjoern Hoehrmann < bjoern @ hoehrmann . de >
2021-06-19 15:11:23 +03:00
Permission is hereby granted , free of charge , to any person obtaining a copy of this software and associated
documentation files ( the " Software " ) , to deal in the Software without restriction , including without
limitation the rights to use , copy , modify , merge , publish , distribute , sublicense , and / or sell copies of the
Software , and to permit persons to whom the Software is furnished to do so , subject to the following
conditions :
2019-11-27 19:16:14 +03:00
2021-06-19 15:11:23 +03:00
The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software .
2019-11-27 19:16:14 +03:00
See https : //bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
*/
static const unsigned char utf8d [ ] = {
/* The first part of the table maps bytes to character classes that
* reduce the size of the transition table and create bitmasks . */
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 ,
7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 ,
8 , 8 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
10 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 4 , 3 , 3 , 11 , 6 , 6 , 6 , 5 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 ,
/* The second part is a transition table that maps a combination
* of a state of the automaton and a character class to a state . */
0 , 12 , 24 , 36 , 60 , 96 , 84 , 12 , 12 , 12 , 48 , 72 , 12 , 12 , 12 , 12 , 12 , 12 , 12 , 12 , 12 , 12 , 12 , 12 ,
12 , 0 , 12 , 12 , 12 , 12 , 12 , 0 , 12 , 0 , 12 , 12 , 12 , 24 , 12 , 12 , 12 , 12 , 12 , 24 , 12 , 24 , 12 , 12 ,
12 , 12 , 12 , 12 , 12 , 12 , 12 , 24 , 12 , 12 , 12 , 12 , 12 , 24 , 12 , 12 , 12 , 12 , 12 , 12 , 12 , 24 , 12 , 12 ,
12 , 12 , 12 , 12 , 12 , 12 , 12 , 36 , 12 , 36 , 12 , 12 , 12 , 36 , 12 , 12 , 12 , 12 , 12 , 36 , 12 , 36 , 12 , 12 ,
12 , 36 , 12 , 12 , 12 , 12 , 12 , 12 , 12 , 12 , 12 , 12 ,
} ;
2021-10-31 00:00:31 +03:00
const unsigned int type = utf8d [ byte ] ;
2019-11-27 19:16:14 +03:00
* codep = * state ! = 0 ? ( byte & 0x3fu ) | ( * codep < < 6 ) : ( 0xff > > type ) & byte ;
* state = utf8d [ 256 + * state + type ] ;
return * state ;
}
2021-03-21 20:35:52 +03:00
/* Is string valid UTF-8? */
INTERNAL int is_valid_utf8 ( const unsigned char source [ ] , const int length ) {
int i ;
unsigned int codepoint , state = 0 ;
for ( i = 0 ; i < length ; i + + ) {
if ( decode_utf8 ( & state , & codepoint , source [ i ] ) = = 12 ) {
return 0 ;
}
}
return state = = 0 ;
}
2022-11-07 01:25:19 +03:00
/* Converts UTF-8 to Unicode. If `disallow_4byte` unset, allows all values (UTF-32). If `disallow_4byte` set,
* only allows codepoints < = U + FFFF ( ie four - byte sequences not allowed ) ( UTF - 16 , no surrogates ) */
2020-11-27 15:54:44 +03:00
INTERNAL int utf8_to_unicode ( struct zint_symbol * symbol , const unsigned char source [ ] , unsigned int vals [ ] ,
2023-06-12 03:25:55 +03:00
int * length , const int disallow_4byte ) {
2020-11-27 15:54:44 +03:00
int bpos ;
int jpos ;
2019-11-27 19:16:14 +03:00
unsigned int codepoint , state = 0 ;
2016-02-20 12:38:03 +03:00
bpos = 0 ;
jpos = 0 ;
2019-11-27 19:16:14 +03:00
while ( bpos < * length ) {
do {
decode_utf8 ( & state , & codepoint , source [ bpos + + ] ) ;
} while ( bpos < * length & & state ! = 0 & & state ! = 12 ) ;
if ( state ! = 0 ) {
strcpy ( symbol - > errtxt , " 240: Corrupt Unicode data " ) ;
return ZINT_ERROR_INVALID_DATA ;
}
2019-12-08 19:15:34 +03:00
if ( disallow_4byte & & codepoint > 0xffff ) {
2019-11-27 19:16:14 +03:00
strcpy ( symbol - > errtxt , " 242: Unicode sequences of more than 3 bytes not supported " ) ;
return ZINT_ERROR_INVALID_DATA ;
2016-02-20 12:38:03 +03:00
}
2019-11-27 19:16:14 +03:00
vals [ jpos ] = codepoint ;
jpos + + ;
}
2019-12-04 16:45:01 +03:00
2016-02-20 12:38:03 +03:00
* length = jpos ;
2019-11-27 19:16:14 +03:00
return 0 ;
2009-10-06 23:03:00 +04:00
}
2009-09-29 13:45:46 +04:00
2023-06-12 03:25:55 +03:00
/* Treats source as ISO/IEC 8859-1 and copies into `symbol->text`, converting to UTF-8. Control chars (incl. DEL) and
non - ISO / IEC 8859 - 1 ( 0x80 - 9F ) are replaced with spaces . Returns warning if truncated , else 0 */
INTERNAL int hrt_cpy_iso8859_1 ( struct zint_symbol * symbol , const unsigned char source [ ] , const int length ) {
int i , j ;
int warn_number = 0 ;
for ( i = 0 , j = 0 ; i < length & & j < ( int ) sizeof ( symbol - > text ) ; i + + ) {
if ( source [ i ] < 0x80 ) {
symbol - > text [ j + + ] = source [ i ] > = ' ' & & source [ i ] ! = 0x7F ? source [ i ] : ' ' ;
} else if ( source [ i ] < 0xC0 ) {
if ( source [ i ] > = 0xA0 ) { /* 0x80-0x9F not valid ISO/IEC 8859-1 */
if ( j + 2 > = ( int ) sizeof ( symbol - > text ) ) {
warn_number = ZINT_WARN_HRT_TRUNCATED ;
break ;
}
symbol - > text [ j + + ] = 0xC2 ;
symbol - > text [ j + + ] = source [ i ] ;
} else {
symbol - > text [ j + + ] = ' ' ;
}
} else {
if ( j + 2 > = ( int ) sizeof ( symbol - > text ) ) {
warn_number = ZINT_WARN_HRT_TRUNCATED ;
break ;
}
symbol - > text [ j + + ] = 0xC3 ;
symbol - > text [ j + + ] = source [ i ] - 0x40 ;
}
}
if ( j = = sizeof ( symbol - > text ) ) {
warn_number = ZINT_WARN_HRT_TRUNCATED ;
j - - ;
}
symbol - > text [ j ] = ' \0 ' ;
if ( warn_number ) {
strcpy ( symbol - > errtxt , " 249: Human Readable Text truncated " ) ;
}
return warn_number ;
}
2022-11-07 01:25:19 +03:00
/* Sets symbol height, returning a warning if not within minimum and/or maximum if given.
2021-06-19 15:11:23 +03:00
` default_height ` does not include height of fixed - height rows ( i . e . separators / composite data ) */
INTERNAL int set_height ( struct zint_symbol * symbol , const float min_row_height , const float default_height ,
2023-06-12 03:25:55 +03:00
const float max_height , const int no_errtxt ) {
2021-06-19 15:11:23 +03:00
int error_number = 0 ;
float fixed_height = 0.0f ;
2016-10-14 20:56:49 +03:00
int zero_count = 0 ;
2021-06-19 15:11:23 +03:00
float row_height ;
2016-10-14 20:56:49 +03:00
int i ;
2021-10-31 00:00:31 +03:00
const int rows = symbol - > rows ? symbol - > rows : 1 ; /* Sometimes called before expand() */
2017-10-23 22:37:52 +03:00
2021-06-19 15:11:23 +03:00
for ( i = 0 ; i < rows ; i + + ) {
if ( symbol - > row_height [ i ] ) {
fixed_height + = symbol - > row_height [ i ] ;
} else {
2016-10-14 20:56:49 +03:00
zero_count + + ;
}
}
2017-10-23 22:37:52 +03:00
2021-06-19 15:11:23 +03:00
if ( zero_count ) {
if ( symbol - > height ) {
2021-11-20 14:32:30 +03:00
if ( symbol - > input_mode & HEIGHTPERROW_MODE ) {
row_height = stripf ( symbol - > height ) ;
} else {
row_height = stripf ( ( symbol - > height - fixed_height ) / zero_count ) ;
}
2021-06-19 15:11:23 +03:00
} else if ( default_height ) {
Add compliant height, using ZINT_COMPLIANT_HEIGHT flag for back-compatibility
Rename barcode funcs to same as BARCODE_XXX name
library: barcode funcs array for dispatch, used for ZBarcode_ValidID() also
general: change is_sane() comparison to nonzero from ZINT_ERROR_INVALID_OPTION
MAILMARK: fuller error messages
CODABAR: add option to show check character in HRT
zint.h: use 0xNNNN for OR-able defines
GUI: add guard descent height reset button, add Zint version to window title,
static get_zint_version() method, use QStringLiteral (QSL shorthand),
use SIGNAL(toggled()), add errtxt "popup" and status bar, add icons,
add saveAs shortcut, add main menu, context menus and actions, add help,
reset_view() -> reset_colours(), add copy to clipboard as EMF/GIF/PNG/TIF,
lessen triggering of update_preview(), shorten names of getters/setters,
simplify/shorten some update_preview() logic in switch,
CODEONE disable structapp for Version S
qzint.cpp: add on_errored signal, add missing getters, add test
2021-10-09 02:13:39 +03:00
row_height = stripf ( default_height / zero_count ) ;
2021-06-19 15:11:23 +03:00
} else {
Add compliant height, using ZINT_COMPLIANT_HEIGHT flag for back-compatibility
Rename barcode funcs to same as BARCODE_XXX name
library: barcode funcs array for dispatch, used for ZBarcode_ValidID() also
general: change is_sane() comparison to nonzero from ZINT_ERROR_INVALID_OPTION
MAILMARK: fuller error messages
CODABAR: add option to show check character in HRT
zint.h: use 0xNNNN for OR-able defines
GUI: add guard descent height reset button, add Zint version to window title,
static get_zint_version() method, use QStringLiteral (QSL shorthand),
use SIGNAL(toggled()), add errtxt "popup" and status bar, add icons,
add saveAs shortcut, add main menu, context menus and actions, add help,
reset_view() -> reset_colours(), add copy to clipboard as EMF/GIF/PNG/TIF,
lessen triggering of update_preview(), shorten names of getters/setters,
simplify/shorten some update_preview() logic in switch,
CODEONE disable structapp for Version S
qzint.cpp: add on_errored signal, add missing getters, add test
2021-10-09 02:13:39 +03:00
row_height = stripf ( min_row_height ) ;
2021-06-19 15:11:23 +03:00
}
if ( row_height < 0.5f ) { /* Absolute minimum */
row_height = 0.5f ;
}
2022-09-05 17:11:46 +03:00
if ( min_row_height ) {
2022-09-06 17:58:53 +03:00
if ( stripf ( row_height ) < stripf ( min_row_height ) ) {
2022-09-05 17:11:46 +03:00
error_number = ZINT_WARN_NONCOMPLIANT ;
if ( ! no_errtxt ) {
strcpy ( symbol - > errtxt , " 247: Height not compliant with standards " ) ;
}
2016-10-14 20:56:49 +03:00
}
}
Add compliant height, using ZINT_COMPLIANT_HEIGHT flag for back-compatibility
Rename barcode funcs to same as BARCODE_XXX name
library: barcode funcs array for dispatch, used for ZBarcode_ValidID() also
general: change is_sane() comparison to nonzero from ZINT_ERROR_INVALID_OPTION
MAILMARK: fuller error messages
CODABAR: add option to show check character in HRT
zint.h: use 0xNNNN for OR-able defines
GUI: add guard descent height reset button, add Zint version to window title,
static get_zint_version() method, use QStringLiteral (QSL shorthand),
use SIGNAL(toggled()), add errtxt "popup" and status bar, add icons,
add saveAs shortcut, add main menu, context menus and actions, add help,
reset_view() -> reset_colours(), add copy to clipboard as EMF/GIF/PNG/TIF,
lessen triggering of update_preview(), shorten names of getters/setters,
simplify/shorten some update_preview() logic in switch,
CODEONE disable structapp for Version S
qzint.cpp: add on_errored signal, add missing getters, add test
2021-10-09 02:13:39 +03:00
symbol - > height = stripf ( row_height * zero_count + fixed_height ) ;
2021-06-19 15:11:23 +03:00
} else {
Add compliant height, using ZINT_COMPLIANT_HEIGHT flag for back-compatibility
Rename barcode funcs to same as BARCODE_XXX name
library: barcode funcs array for dispatch, used for ZBarcode_ValidID() also
general: change is_sane() comparison to nonzero from ZINT_ERROR_INVALID_OPTION
MAILMARK: fuller error messages
CODABAR: add option to show check character in HRT
zint.h: use 0xNNNN for OR-able defines
GUI: add guard descent height reset button, add Zint version to window title,
static get_zint_version() method, use QStringLiteral (QSL shorthand),
use SIGNAL(toggled()), add errtxt "popup" and status bar, add icons,
add saveAs shortcut, add main menu, context menus and actions, add help,
reset_view() -> reset_colours(), add copy to clipboard as EMF/GIF/PNG/TIF,
lessen triggering of update_preview(), shorten names of getters/setters,
simplify/shorten some update_preview() logic in switch,
CODEONE disable structapp for Version S
qzint.cpp: add on_errored signal, add missing getters, add test
2021-10-09 02:13:39 +03:00
symbol - > height = stripf ( fixed_height ) ; /* Ignore any given height */
2021-06-19 15:11:23 +03:00
}
2022-09-05 17:11:46 +03:00
if ( max_height ) {
2022-09-06 17:58:53 +03:00
if ( stripf ( symbol - > height ) > stripf ( max_height ) ) {
2022-09-05 17:11:46 +03:00
error_number = ZINT_WARN_NONCOMPLIANT ;
if ( ! no_errtxt ) {
strcpy ( symbol - > errtxt , " 248: Height not compliant with standards " ) ;
}
2021-06-19 15:11:23 +03:00
}
2016-10-14 20:56:49 +03:00
}
2021-06-19 15:11:23 +03:00
return error_number ;
2016-10-14 20:56:49 +03:00
}
2017-10-23 22:37:52 +03:00
2022-09-06 17:58:53 +03:00
/* Prevent inlining of `stripf()` which can optimize away its effect */
# if defined(__GNUC__) || defined(__clang__)
__attribute__ ( ( __noinline__ ) )
# endif
# if defined(_MSC_VER) && _MSC_VER >= 1310 /* MSVC 2003 (VC++ 7.1) */
__declspec ( noinline )
# endif
Add Structured Append support for AZTEC, CODEONE, DATAMATRIX, DOTCODE,
GRIDMATRIX, MAXICODE, MICROPDF417, PDF417, QRCODE, ULTRA
DOTCODE: use pre-calculated generator poly coeffs in Reed-Solomon for
performance improvement
PDF417/MICROPDF417: use common routine pdf417_initial()
GUI: code lines <= 118, shorthand widget_obj(),
shorten calling upcean_addon_gap(), upcean_guard_descent()
various backend: var name debug -> debug_print
2021-09-28 23:42:44 +03:00
/* Removes excess precision from floats - see https://stackoverflow.com/q/503436 */
2021-09-27 01:55:16 +03:00
INTERNAL float stripf ( const float arg ) {
return * ( ( volatile const float * ) & arg ) ;
}
Add multiple segments support for AZTEC, CODEONE, DATAMATRIX, DOTCODE,
GRIDMATRIX, HANXIN, MAXICODE, MICROPDF417, PDF417, QRCODE, RMQR, ULTRA
RMQR: fix ECI encoding (wrong bit length for indicator)
MICROQR: check versions M1 and M2 for allowed characters so as to give
better error messages
DOTCODE: some small optimizations
common.c: add is_chr(), segs_length(), segs_cpy()
CODEONE/CODE128/DOTCODE/GRIDMATRIX/HANXIN/MAXICODE/QRCODE/ULTRA: add
namespace prefixes to static funcs/data
includes: use Z_ prefix, unuse double underscore prefixes (guard defines)
manual.txt: compress some tables using double/treble column sets
2022-05-09 21:50:50 +03:00
/* Returns total length of segments */
INTERNAL int segs_length ( const struct zint_seg segs [ ] , const int seg_count ) {
int total_len = 0 ;
int i ;
for ( i = 0 ; i < seg_count ; i + + ) {
total_len + = segs [ i ] . length = = - 1 ? ( int ) ustrlen ( segs [ i ] . source ) : segs [ i ] . length ;
}
return total_len ;
}
2022-11-07 01:25:19 +03:00
/* Shallow copies segments, adjusting default ECIs */
2022-05-19 12:17:51 +03:00
INTERNAL void segs_cpy ( const struct zint_symbol * symbol , const struct zint_seg segs [ ] , const int seg_count ,
2023-06-12 03:25:55 +03:00
struct zint_seg local_segs [ ] ) {
2022-05-19 12:17:51 +03:00
const int default_eci = symbol - > symbology = = BARCODE_GRIDMATRIX ? 29 : symbol - > symbology = = BARCODE_UPNQR ? 4 : 3 ;
Add multiple segments support for AZTEC, CODEONE, DATAMATRIX, DOTCODE,
GRIDMATRIX, HANXIN, MAXICODE, MICROPDF417, PDF417, QRCODE, RMQR, ULTRA
RMQR: fix ECI encoding (wrong bit length for indicator)
MICROQR: check versions M1 and M2 for allowed characters so as to give
better error messages
DOTCODE: some small optimizations
common.c: add is_chr(), segs_length(), segs_cpy()
CODEONE/CODE128/DOTCODE/GRIDMATRIX/HANXIN/MAXICODE/QRCODE/ULTRA: add
namespace prefixes to static funcs/data
includes: use Z_ prefix, unuse double underscore prefixes (guard defines)
manual.txt: compress some tables using double/treble column sets
2022-05-09 21:50:50 +03:00
int i ;
local_segs [ 0 ] = segs [ 0 ] ;
for ( i = 1 ; i < seg_count ; i + + ) {
local_segs [ i ] = segs [ i ] ;
/* Ensure default ECI set if follows non-default ECI */
2022-05-19 12:17:51 +03:00
if ( local_segs [ i ] . eci = = 0 & & local_segs [ i - 1 ] . eci ! = 0 & & local_segs [ i - 1 ] . eci ! = default_eci ) {
local_segs [ i ] . eci = default_eci ;
Add multiple segments support for AZTEC, CODEONE, DATAMATRIX, DOTCODE,
GRIDMATRIX, HANXIN, MAXICODE, MICROPDF417, PDF417, QRCODE, RMQR, ULTRA
RMQR: fix ECI encoding (wrong bit length for indicator)
MICROQR: check versions M1 and M2 for allowed characters so as to give
better error messages
DOTCODE: some small optimizations
common.c: add is_chr(), segs_length(), segs_cpy()
CODEONE/CODE128/DOTCODE/GRIDMATRIX/HANXIN/MAXICODE/QRCODE/ULTRA: add
namespace prefixes to static funcs/data
includes: use Z_ prefix, unuse double underscore prefixes (guard defines)
manual.txt: compress some tables using double/treble column sets
2022-05-09 21:50:50 +03:00
}
}
}
2023-11-30 12:12:11 +03:00
/* Helper for ZINT_DEBUG_PRINT to put all but graphical ASCII in angle brackets */
INTERNAL char * debug_print_escape ( const unsigned char * source , const int first_len , char * buf ) {
int i , j = 0 ;
for ( i = 0 ; i < first_len ; i + + ) {
const unsigned char ch = source [ i ] ;
if ( ch < 32 | | ch > = 127 ) {
j + = sprintf ( buf + j , " <%03o> " , ch & 0xFF ) ;
} else {
buf [ j + + ] = ch ;
}
}
buf [ j ] = ' \0 ' ;
return buf ;
}
2019-12-19 03:37:55 +03:00
# ifdef ZINT_TEST
2019-12-16 20:31:52 +03:00
/* Dumps hex-formatted codewords in symbol->errtxt (for use in testing) */
2023-06-12 03:25:55 +03:00
INTERNAL void debug_test_codeword_dump ( struct zint_symbol * symbol , const unsigned char * codewords , const int length ) {
2019-12-16 20:31:52 +03:00
int i , max = length , cnt_len = 0 ;
if ( length > 30 ) { /* 30*3 < errtxt 92 (100 - "Warning ") chars */
sprintf ( symbol - > errtxt , " (%d) " , length ) ; /* Place the number of codewords at the front */
2021-06-10 13:15:39 +03:00
cnt_len = ( int ) strlen ( symbol - > errtxt ) ;
2019-12-16 20:31:52 +03:00
max = 30 - ( cnt_len + 2 ) / 3 ;
}
for ( i = 0 ; i < max ; i + + ) {
sprintf ( symbol - > errtxt + cnt_len + i * 3 , " %02X " , codewords [ i ] ) ;
}
symbol - > errtxt [ strlen ( symbol - > errtxt ) - 1 ] = ' \0 ' ; /* Zap last space */
}
2020-04-10 00:08:54 +03:00
2023-11-27 15:55:53 +03:00
/* Dumps decimal-formatted codewords in symbol->errtxt (for use in testing) */
INTERNAL void debug_test_codeword_dump_short ( struct zint_symbol * symbol , const short * codewords , const int length ) {
int i , max = 0 , cnt_len , errtxt_len ;
char temp [ 20 ] ;
errtxt_len = sprintf ( symbol - > errtxt , " (%d) " , length ) ; /* Place the number of codewords at the front */
for ( i = 0 , cnt_len = errtxt_len ; i < length ; i + + ) {
cnt_len + = sprintf ( temp , " %d " , codewords [ i ] ) ;
if ( cnt_len > 92 ) {
break ;
}
max + + ;
}
for ( i = 0 ; i < max ; i + + ) {
errtxt_len + = sprintf ( symbol - > errtxt + errtxt_len , " %d " , codewords [ i ] ) ;
}
symbol - > errtxt [ strlen ( symbol - > errtxt ) - 1 ] = ' \0 ' ; /* Zap last space */
}
2020-12-19 20:13:35 +03:00
/* Dumps decimal-formatted codewords in symbol->errtxt (for use in testing) */
2023-06-12 03:25:55 +03:00
INTERNAL void debug_test_codeword_dump_int ( struct zint_symbol * symbol , const int * codewords , const int length ) {
2020-04-10 00:08:54 +03:00
int i , max = 0 , cnt_len , errtxt_len ;
char temp [ 20 ] ;
errtxt_len = sprintf ( symbol - > errtxt , " (%d) " , length ) ; /* Place the number of codewords at the front */
for ( i = 0 , cnt_len = errtxt_len ; i < length ; i + + ) {
cnt_len + = sprintf ( temp , " %d " , codewords [ i ] ) ;
if ( cnt_len > 92 ) {
break ;
}
max + + ;
}
for ( i = 0 ; i < max ; i + + ) {
errtxt_len + = sprintf ( symbol - > errtxt + errtxt_len , " %d " , codewords [ i ] ) ;
}
symbol - > errtxt [ strlen ( symbol - > errtxt ) - 1 ] = ' \0 ' ; /* Zap last space */
}
2019-12-19 03:37:55 +03:00
# endif
Add multiple segments support for AZTEC, CODEONE, DATAMATRIX, DOTCODE,
GRIDMATRIX, HANXIN, MAXICODE, MICROPDF417, PDF417, QRCODE, RMQR, ULTRA
RMQR: fix ECI encoding (wrong bit length for indicator)
MICROQR: check versions M1 and M2 for allowed characters so as to give
better error messages
DOTCODE: some small optimizations
common.c: add is_chr(), segs_length(), segs_cpy()
CODEONE/CODE128/DOTCODE/GRIDMATRIX/HANXIN/MAXICODE/QRCODE/ULTRA: add
namespace prefixes to static funcs/data
includes: use Z_ prefix, unuse double underscore prefixes (guard defines)
manual.txt: compress some tables using double/treble column sets
2022-05-09 21:50:50 +03:00
/* vim: set ts=4 sw=4 et : */