2016-07-20 01:02:39 +03:00
/* raster.c - Handles output to raster files */
/*
libzint - the open source barcode library
2020-04-03 21:40:59 +03:00
Copyright ( C ) 2009 - 2020 Robin Stuart < rstuart114 @ gmail . com >
2016-07-20 01:02:39 +03:00
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
2017-10-23 22:37:52 +03:00
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2016-07-20 01:02:39 +03:00
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
2017-10-23 22:37:52 +03:00
documentation and / or other materials provided with the distribution .
2016-07-20 01:02:39 +03:00
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
2017-10-23 22:37:52 +03:00
without specific prior written permission .
2016-07-20 01:02:39 +03:00
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS " AND
ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY
2017-10-23 22:37:52 +03:00
OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
2016-07-20 01:02:39 +03:00
SUCH DAMAGE .
*/
2019-11-12 00:38:21 +03:00
/* vim: set ts=4 sw=4 et : */
2016-07-20 01:02:39 +03:00
# include <stdio.h>
# ifdef _MSC_VER
2020-07-19 12:31:12 +03:00
# include <malloc.h>
2016-07-20 01:02:39 +03:00
# include <fcntl.h>
# include <io.h>
# endif
2020-07-15 21:00:12 +03:00
# include <math.h>
2020-07-19 12:31:12 +03:00
# include <assert.h>
2016-07-20 01:02:39 +03:00
# include "common.h"
2020-05-21 20:22:28 +03:00
# include "output.h"
2016-07-20 01:02:39 +03:00
2016-08-09 01:18:55 +03:00
# include "font.h" /* Font for human readable text */
2016-07-20 01:02:39 +03:00
2020-07-15 21:00:12 +03:00
# define SSET "0123456789ABCDEF"
2016-10-27 19:50:10 +03:00
2020-01-06 23:01:48 +03:00
# define DEFAULT_INK '1'
# define DEFAULT_PAPER '0'
2016-07-20 01:02:39 +03:00
# ifndef NO_PNG
2019-12-19 03:37:55 +03:00
INTERNAL int png_pixel_plot ( struct zint_symbol * symbol , char * pixelbuf ) ;
2016-07-20 01:02:39 +03:00
# endif /* NO_PNG */
2019-12-19 03:37:55 +03:00
INTERNAL int bmp_pixel_plot ( struct zint_symbol * symbol , char * pixelbuf ) ;
INTERNAL int pcx_pixel_plot ( struct zint_symbol * symbol , char * pixelbuf ) ;
INTERNAL int gif_pixel_plot ( struct zint_symbol * symbol , char * pixelbuf ) ;
INTERNAL int tif_pixel_plot ( struct zint_symbol * symbol , char * pixelbuf ) ;
2016-07-20 01:02:39 +03:00
2020-01-06 23:01:48 +03:00
static const char ultra_colour [ ] = " WCBMRYGK " ;
2020-06-04 20:45:25 +03:00
static int buffer_plot ( struct zint_symbol * symbol , char * pixelbuf ) {
2016-10-02 12:45:47 +03:00
/* Place pixelbuffer into symbol */
int fgred , fggrn , fgblu , bgred , bggrn , bgblu ;
2020-08-03 00:26:39 +03:00
int fgalpha , bgalpha ;
2016-10-02 12:45:47 +03:00
int row , column , i ;
2020-08-03 09:53:54 +03:00
int plot_alpha = 0 ;
if ( strlen ( symbol - > fgcolour ) > 6 ) {
fgalpha = ( 16 * ctoi ( symbol - > fgcolour [ 6 ] ) ) + ctoi ( symbol - > fgcolour [ 7 ] ) ;
plot_alpha = 1 ;
} else {
fgalpha = 0xff ;
}
if ( strlen ( symbol - > bgcolour ) > 6 ) {
bgalpha = ( 16 * ctoi ( symbol - > bgcolour [ 6 ] ) ) + ctoi ( symbol - > bgcolour [ 7 ] ) ;
plot_alpha = 1 ;
} else {
bgalpha = 0xff ;
}
2017-10-23 22:37:52 +03:00
2020-07-15 21:00:12 +03:00
/* Free any previous bitmap */
2020-06-04 20:45:25 +03:00
if ( symbol - > bitmap ! = NULL ) {
free ( symbol - > bitmap ) ;
symbol - > bitmap = NULL ;
}
2020-08-03 09:53:54 +03:00
if ( symbol - > alphamap ! = NULL ) {
free ( symbol - > alphamap ) ;
symbol - > alphamap = NULL ;
}
2020-03-29 15:42:33 +03:00
symbol - > bitmap = ( unsigned char * ) malloc ( symbol - > bitmap_width * symbol - > bitmap_height * 3 ) ;
2020-06-04 20:45:25 +03:00
if ( symbol - > bitmap = = NULL ) {
strcpy ( symbol - > errtxt , " 661: Insufficient memory for bitmap buffer " ) ;
return ZINT_ERROR_MEMORY ;
}
2020-08-03 09:53:54 +03:00
if ( plot_alpha ) {
symbol - > alphamap = ( unsigned char * ) malloc ( symbol - > bitmap_width * symbol - > bitmap_height ) ;
if ( symbol - > alphamap = = NULL ) {
strcpy ( symbol - > errtxt , " 662: Insufficient memory for alphamap buffer " ) ;
return ZINT_ERROR_MEMORY ;
}
2020-08-03 00:26:39 +03:00
}
2017-10-23 22:37:52 +03:00
2016-10-02 12:45:47 +03:00
fgred = ( 16 * ctoi ( symbol - > fgcolour [ 0 ] ) ) + ctoi ( symbol - > fgcolour [ 1 ] ) ;
fggrn = ( 16 * ctoi ( symbol - > fgcolour [ 2 ] ) ) + ctoi ( symbol - > fgcolour [ 3 ] ) ;
fgblu = ( 16 * ctoi ( symbol - > fgcolour [ 4 ] ) ) + ctoi ( symbol - > fgcolour [ 5 ] ) ;
bgred = ( 16 * ctoi ( symbol - > bgcolour [ 0 ] ) ) + ctoi ( symbol - > bgcolour [ 1 ] ) ;
bggrn = ( 16 * ctoi ( symbol - > bgcolour [ 2 ] ) ) + ctoi ( symbol - > bgcolour [ 3 ] ) ;
bgblu = ( 16 * ctoi ( symbol - > bgcolour [ 4 ] ) ) + ctoi ( symbol - > bgcolour [ 5 ] ) ;
2020-07-18 11:15:54 +03:00
2016-10-02 12:45:47 +03:00
for ( row = 0 ; row < symbol - > bitmap_height ; row + + ) {
for ( column = 0 ; column < symbol - > bitmap_width ; column + + ) {
i = ( ( row * symbol - > bitmap_width ) + column ) * 3 ;
2016-10-14 18:08:03 +03:00
switch ( * ( pixelbuf + ( symbol - > bitmap_width * row ) + column ) ) {
2020-01-06 23:01:48 +03:00
case ' W ' : // White
symbol - > bitmap [ i ] = 255 ;
symbol - > bitmap [ i + 1 ] = 255 ;
symbol - > bitmap [ i + 2 ] = 255 ;
2020-08-03 09:53:54 +03:00
if ( plot_alpha ) symbol - > alphamap [ i / 3 ] = fgalpha ;
2020-01-06 23:01:48 +03:00
break ;
case ' C ' : // Cyan
symbol - > bitmap [ i ] = 0 ;
symbol - > bitmap [ i + 1 ] = 255 ;
symbol - > bitmap [ i + 2 ] = 255 ;
2020-08-03 09:53:54 +03:00
if ( plot_alpha ) symbol - > alphamap [ i / 3 ] = fgalpha ;
2020-01-06 23:01:48 +03:00
break ;
case ' B ' : // Blue
symbol - > bitmap [ i ] = 0 ;
symbol - > bitmap [ i + 1 ] = 0 ;
symbol - > bitmap [ i + 2 ] = 255 ;
2020-08-03 09:53:54 +03:00
if ( plot_alpha ) symbol - > alphamap [ i / 3 ] = fgalpha ;
2020-01-06 23:01:48 +03:00
break ;
case ' M ' : // Magenta
symbol - > bitmap [ i ] = 255 ;
symbol - > bitmap [ i + 1 ] = 0 ;
symbol - > bitmap [ i + 2 ] = 255 ;
2020-08-03 09:53:54 +03:00
if ( plot_alpha ) symbol - > alphamap [ i / 3 ] = fgalpha ;
2020-01-06 23:01:48 +03:00
break ;
case ' R ' : // Red
symbol - > bitmap [ i ] = 255 ;
symbol - > bitmap [ i + 1 ] = 0 ;
symbol - > bitmap [ i + 2 ] = 0 ;
2020-08-03 09:53:54 +03:00
if ( plot_alpha ) symbol - > alphamap [ i / 3 ] = fgalpha ;
2020-01-06 23:01:48 +03:00
break ;
case ' Y ' : // Yellow
symbol - > bitmap [ i ] = 255 ;
symbol - > bitmap [ i + 1 ] = 255 ;
symbol - > bitmap [ i + 2 ] = 0 ;
2020-08-03 09:53:54 +03:00
if ( plot_alpha ) symbol - > alphamap [ i / 3 ] = fgalpha ;
2020-01-06 23:01:48 +03:00
break ;
case ' G ' : // Green
symbol - > bitmap [ i ] = 0 ;
symbol - > bitmap [ i + 1 ] = 255 ;
symbol - > bitmap [ i + 2 ] = 0 ;
2020-08-03 09:53:54 +03:00
if ( plot_alpha ) symbol - > alphamap [ i / 3 ] = fgalpha ;
2020-01-06 23:01:48 +03:00
break ;
case ' K ' : // Black
symbol - > bitmap [ i ] = 0 ;
symbol - > bitmap [ i + 1 ] = 0 ;
symbol - > bitmap [ i + 2 ] = 0 ;
2020-08-03 09:53:54 +03:00
if ( plot_alpha ) symbol - > alphamap [ i / 3 ] = fgalpha ;
2020-01-06 23:01:48 +03:00
break ;
case DEFAULT_INK :
2016-10-02 12:45:47 +03:00
symbol - > bitmap [ i ] = fgred ;
symbol - > bitmap [ i + 1 ] = fggrn ;
symbol - > bitmap [ i + 2 ] = fgblu ;
2020-08-03 09:53:54 +03:00
if ( plot_alpha ) symbol - > alphamap [ i / 3 ] = fgalpha ;
2016-10-02 12:45:47 +03:00
break ;
2020-01-06 23:01:48 +03:00
default : // DEFAULT_PAPER
2016-10-02 12:45:47 +03:00
symbol - > bitmap [ i ] = bgred ;
symbol - > bitmap [ i + 1 ] = bggrn ;
symbol - > bitmap [ i + 2 ] = bgblu ;
2020-08-03 09:53:54 +03:00
if ( plot_alpha ) symbol - > alphamap [ i / 3 ] = bgalpha ;
2016-10-02 12:45:47 +03:00
break ;
}
}
}
2020-06-04 20:45:25 +03:00
return 0 ;
2016-10-02 12:45:47 +03:00
}
2019-12-19 03:37:55 +03:00
static int save_raster_image_to_file ( struct zint_symbol * symbol , int image_height , int image_width , char * pixelbuf , int rotate_angle , int image_type ) {
2016-07-20 01:02:39 +03:00
int error_number ;
2016-09-11 10:42:31 +03:00
int row , column ;
2017-10-23 22:37:52 +03:00
2020-05-21 20:22:28 +03:00
char * rotated_pixbuf = pixelbuf ;
2016-07-20 01:02:39 +03:00
2016-09-11 10:42:31 +03:00
switch ( rotate_angle ) {
case 0 :
case 180 :
symbol - > bitmap_width = image_width ;
symbol - > bitmap_height = image_height ;
break ;
case 90 :
case 270 :
symbol - > bitmap_width = image_height ;
symbol - > bitmap_height = image_width ;
break ;
}
2017-10-23 22:37:52 +03:00
2020-05-21 20:22:28 +03:00
if ( rotate_angle ) {
if ( ! ( rotated_pixbuf = ( char * ) malloc ( image_width * image_height ) ) ) {
strcpy ( symbol - > errtxt , " 650: Insufficient memory for pixel buffer " ) ;
return ZINT_ERROR_ENCODING_PROBLEM ;
}
2016-09-11 10:42:31 +03:00
}
2017-10-23 22:37:52 +03:00
2016-09-11 10:42:31 +03:00
/* Rotate image before plotting */
switch ( rotate_angle ) {
case 0 : /* Plot the right way up */
2020-05-21 20:22:28 +03:00
/* Nothing to do */
2016-09-11 10:42:31 +03:00
break ;
case 90 : /* Plot 90 degrees clockwise */
for ( row = 0 ; row < image_width ; row + + ) {
for ( column = 0 ; column < image_height ; column + + ) {
rotated_pixbuf [ ( row * image_height ) + column ] =
* ( pixelbuf + ( image_width * ( image_height - column - 1 ) ) + row ) ;
}
}
break ;
case 180 : /* Plot upside down */
for ( row = 0 ; row < image_height ; row + + ) {
for ( column = 0 ; column < image_width ; column + + ) {
rotated_pixbuf [ ( row * image_width ) + column ] =
* ( pixelbuf + ( image_width * ( image_height - row - 1 ) ) + ( image_width - column - 1 ) ) ;
}
}
break ;
case 270 : /* Plot 90 degrees anti-clockwise */
for ( row = 0 ; row < image_width ; row + + ) {
for ( column = 0 ; column < image_height ; column + + ) {
rotated_pixbuf [ ( row * image_height ) + column ] =
* ( pixelbuf + ( image_width * column ) + ( image_width - row - 1 ) ) ;
}
}
break ;
}
2017-10-23 22:37:52 +03:00
2016-08-09 01:18:55 +03:00
switch ( image_type ) {
2016-10-02 12:45:47 +03:00
case OUT_BUFFER :
2020-06-04 20:45:25 +03:00
error_number = buffer_plot ( symbol , rotated_pixbuf ) ;
2016-10-02 12:45:47 +03:00
break ;
2016-07-23 17:08:55 +03:00
case OUT_PNG_FILE :
2016-07-20 01:02:39 +03:00
# ifndef NO_PNG
2016-09-11 10:42:31 +03:00
error_number = png_pixel_plot ( symbol , rotated_pixbuf ) ;
2016-07-20 01:02:39 +03:00
# else
2020-05-21 20:22:28 +03:00
if ( rotate_angle ) {
free ( rotated_pixbuf ) ;
}
2016-07-23 17:08:55 +03:00
return ZINT_ERROR_INVALID_OPTION ;
2016-07-20 01:02:39 +03:00
# endif
2016-07-23 17:08:55 +03:00
break ;
case OUT_PCX_FILE :
2016-09-11 10:42:31 +03:00
error_number = pcx_pixel_plot ( symbol , rotated_pixbuf ) ;
2016-08-09 01:18:55 +03:00
break ;
case OUT_GIF_FILE :
2016-09-11 10:42:31 +03:00
error_number = gif_pixel_plot ( symbol , rotated_pixbuf ) ;
2016-07-23 17:08:55 +03:00
break ;
2016-12-30 23:25:58 +03:00
case OUT_TIF_FILE :
error_number = tif_pixel_plot ( symbol , rotated_pixbuf ) ;
break ;
2016-07-23 17:08:55 +03:00
default :
2016-09-11 10:42:31 +03:00
error_number = bmp_pixel_plot ( symbol , rotated_pixbuf ) ;
2016-07-23 17:08:55 +03:00
break ;
2016-07-20 01:02:39 +03:00
}
2020-05-21 20:22:28 +03:00
if ( rotate_angle ) {
free ( rotated_pixbuf ) ;
}
2016-07-20 01:02:39 +03:00
return error_number ;
}
2020-04-06 19:05:22 +03:00
static void draw_bar ( char * pixelbuf , int xpos , int xlen , int ypos , int ylen , int image_width , int image_height , char fill ) {
2016-07-20 01:02:39 +03:00
/* Draw a rectangle */
int i , j , png_ypos ;
png_ypos = image_height - ypos - ylen ;
/* This fudge is needed because EPS measures height from the bottom up but
PNG measures y position from the top down */
for ( i = ( xpos ) ; i < ( xpos + xlen ) ; i + + ) {
for ( j = ( png_ypos ) ; j < ( png_ypos + ylen ) ; j + + ) {
2020-01-06 23:01:48 +03:00
* ( pixelbuf + ( image_width * j ) + i ) = fill ;
2016-07-20 01:02:39 +03:00
}
}
}
2020-08-09 22:20:16 +03:00
static void draw_circle ( char * pixelbuf , int image_width , int image_height , int x0 , int y0 , float radius , char fill ) {
2016-09-12 23:47:40 +03:00
int x , y ;
2016-09-18 16:09:58 +03:00
int radius_i = ( int ) radius ;
2017-10-23 22:37:52 +03:00
2016-09-18 16:09:58 +03:00
for ( y = - radius_i ; y < = radius_i ; y + + ) {
for ( x = - radius_i ; x < = radius_i ; x + + ) {
if ( ( x * x ) + ( y * y ) < = ( radius_i * radius_i ) ) {
2016-09-12 23:47:40 +03:00
if ( ( y + y0 > = 0 ) & & ( y + y0 < image_height )
& & ( x + x0 > = 0 ) & & ( x + x0 < image_width ) ) {
* ( pixelbuf + ( ( y + y0 ) * image_width ) + ( x + x0 ) ) = fill ;
}
}
}
}
}
2019-12-19 03:37:55 +03:00
static void draw_bullseye ( char * pixelbuf , int image_width , int image_height , int xoffset , int yoffset , int scaler ) {
2019-09-02 13:05:08 +03:00
/* Central bullseye in Maxicode symbols */
2020-08-09 22:20:16 +03:00
float x = 14.5f * scaler ;
float y = 15.0f * scaler ;
if ( scaler < 10 ) {
x = 16.0f * scaler ;
y = 16.5f * scaler ;
2019-09-02 12:26:30 +03:00
}
2020-01-06 23:01:48 +03:00
2020-08-09 22:20:16 +03:00
draw_circle ( pixelbuf , image_width , image_height , x + xoffset , y + yoffset , ( 4.571f * scaler ) + 1.0f , DEFAULT_INK ) ;
draw_circle ( pixelbuf , image_width , image_height , x + xoffset , y + yoffset , ( 3.779f * scaler ) + 1.0f , DEFAULT_PAPER ) ;
draw_circle ( pixelbuf , image_width , image_height , x + xoffset , y + yoffset , ( 2.988f * scaler ) + 1.0f , DEFAULT_INK ) ;
draw_circle ( pixelbuf , image_width , image_height , x + xoffset , y + yoffset , ( 2.196f * scaler ) + 1.0f , DEFAULT_PAPER ) ;
draw_circle ( pixelbuf , image_width , image_height , x + xoffset , y + yoffset , ( 1.394f * scaler ) + 1.0f , DEFAULT_INK ) ;
draw_circle ( pixelbuf , image_width , image_height , x + xoffset , y + yoffset , ( 0.602f * scaler ) + 1.0f , DEFAULT_PAPER ) ;
2016-07-20 01:02:39 +03:00
}
2019-12-19 03:37:55 +03:00
static void draw_hexagon ( char * pixelbuf , int image_width , char * scaled_hexagon , int hexagon_size , int xposn , int yposn ) {
2016-07-20 01:02:39 +03:00
/* Put a hexagon into the pixel buffer */
int i , j ;
2017-10-23 22:37:52 +03:00
2016-10-27 19:50:10 +03:00
for ( i = 0 ; i < hexagon_size ; i + + ) {
for ( j = 0 ; j < hexagon_size ; j + + ) {
2020-01-06 23:01:48 +03:00
if ( scaled_hexagon [ ( i * hexagon_size ) + j ] = = DEFAULT_INK ) {
* ( pixelbuf + ( image_width * i ) + ( image_width * yposn ) + xposn + j ) = DEFAULT_INK ;
2016-07-20 01:02:39 +03:00
}
}
}
}
2019-12-19 03:37:55 +03:00
static void draw_letter ( char * pixelbuf , unsigned char letter , int xposn , int yposn , int textflags , int image_width , int image_height ) {
2016-07-20 01:02:39 +03:00
/* Put a letter into a position */
2017-09-10 18:03:09 +03:00
int skip ;
2016-07-20 01:02:39 +03:00
skip = 0 ;
if ( letter < 33 ) {
skip = 1 ;
}
if ( ( letter > 127 ) & & ( letter < 161 ) ) {
skip = 1 ;
}
if ( xposn < 0 | | yposn < 0 ) {
skip = 1 ;
}
if ( skip = = 0 ) {
2017-09-10 18:03:09 +03:00
int glyph_no ;
2017-10-23 22:34:31 +03:00
int x , y ;
2016-07-20 01:02:39 +03:00
if ( letter > 128 ) {
glyph_no = letter - 66 ;
} else {
glyph_no = letter - 33 ;
}
2016-08-09 01:18:55 +03:00
2016-07-20 01:02:39 +03:00
switch ( textflags ) {
2017-09-10 18:03:09 +03:00
int max_x , max_y ;
2016-08-09 01:18:55 +03:00
case 1 : // small font 5x9
max_x = 5 ;
max_y = 9 ;
2016-07-20 01:02:39 +03:00
2016-08-09 01:18:55 +03:00
if ( xposn + max_x > = image_width ) {
max_x = image_width - xposn - 1 ;
}
if ( yposn + max_y > = image_height ) {
max_y = image_height - yposn - 1 ;
}
for ( y = 0 ; y < max_y ; y + + ) {
for ( x = 0 ; x < max_x ; x + + ) {
if ( small_font [ ( glyph_no * 9 ) + y ] & ( 0x10 > > x ) ) {
2020-01-06 23:01:48 +03:00
* ( pixelbuf + ( y * image_width ) + ( yposn * image_width ) + xposn + x ) = DEFAULT_INK ;
2016-08-09 01:18:55 +03:00
}
}
}
break ;
case 2 : // bold font -> twice the regular font
{
char * linePtr ;
max_x = 7 ;
max_y = 14 ;
2016-07-20 01:02:39 +03:00
2016-08-09 01:18:55 +03:00
if ( xposn + max_x + 1 > = image_width ) {
max_x = image_width - xposn - 2 ;
}
if ( yposn + max_y > = image_height ) {
max_y = image_height - yposn - 1 ;
}
linePtr = pixelbuf + ( yposn * image_width ) + xposn + 1 ;
for ( y = 0 ; y < max_y ; y + + ) {
char * pixelPtr = linePtr ;
int extra_dot = 0 ;
2020-05-21 20:22:28 +03:00
for ( x = 0 ; x < max_x ; x + + ) {
2016-08-09 01:18:55 +03:00
if ( ascii_font [ ( glyph_no * 14 ) + y ] & ( 0x40 > > x ) ) {
2020-01-06 23:01:48 +03:00
* pixelPtr = DEFAULT_INK ;
2016-08-09 01:18:55 +03:00
extra_dot = 1 ;
} else {
if ( extra_dot ) {
2020-01-06 23:01:48 +03:00
* pixelPtr = DEFAULT_INK ;
2016-08-09 01:18:55 +03:00
}
extra_dot = 0 ;
}
+ + pixelPtr ;
}
if ( extra_dot ) {
2020-01-06 23:01:48 +03:00
* pixelPtr = DEFAULT_INK ;
2016-08-09 01:18:55 +03:00
}
linePtr + = image_width ;
}
}
break ;
2020-05-21 20:22:28 +03:00
default : // regular font 7x14
2016-08-09 01:18:55 +03:00
max_x = 7 ;
max_y = 14 ;
2016-07-20 01:02:39 +03:00
2016-08-09 01:18:55 +03:00
if ( xposn + max_x > = image_width ) {
max_x = image_width - xposn - 1 ;
}
if ( yposn + max_y > = image_height ) {
max_y = image_height - yposn - 1 ;
}
2016-07-20 01:02:39 +03:00
2016-08-09 01:18:55 +03:00
for ( y = 0 ; y < max_y ; y + + ) {
2020-05-21 20:22:28 +03:00
for ( x = 0 ; x < max_x ; x + + ) {
2016-08-09 01:18:55 +03:00
if ( ascii_font [ ( glyph_no * 14 ) + y ] & ( 0x40 > > x ) ) {
2020-01-06 23:01:48 +03:00
* ( pixelbuf + ( y * image_width ) + ( yposn * image_width ) + xposn + x ) = DEFAULT_INK ;
2016-08-09 01:18:55 +03:00
}
}
}
break ;
2016-07-20 01:02:39 +03:00
}
}
}
/* Plot a string into the pixel buffer */
2020-07-15 21:00:12 +03:00
static void draw_string ( char * pixbuf , unsigned char input_string [ ] , int xposn , int yposn , int textflags , int image_width , int image_height ) {
2016-07-20 01:02:39 +03:00
int i , string_length , string_left_hand , letter_width = 7 ;
switch ( textflags ) {
2016-08-09 01:18:55 +03:00
case 1 : // small font 5x9
letter_width = 5 ;
break ;
2016-07-20 01:02:39 +03:00
2016-08-09 01:18:55 +03:00
case 2 : // bold font -> width of the regular font + 1 extra dot + 1 extra space
letter_width = 9 ;
break ;
2016-07-20 01:02:39 +03:00
2016-08-09 01:18:55 +03:00
default : // regular font 7x15
letter_width = 7 ;
break ;
2016-07-20 01:02:39 +03:00
}
2016-08-09 01:18:55 +03:00
2020-07-15 21:00:12 +03:00
string_length = ustrlen ( input_string ) ;
2016-07-20 01:02:39 +03:00
string_left_hand = xposn - ( ( letter_width * string_length ) / 2 ) ;
for ( i = 0 ; i < string_length ; i + + ) {
2020-07-19 12:31:12 +03:00
// NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) suppress (probable) false positive about 2nd arg input_string[i] being uninitialized
2016-07-20 01:02:39 +03:00
draw_letter ( pixbuf , input_string [ i ] , string_left_hand + ( i * letter_width ) , yposn , textflags , image_width , image_height ) ;
}
}
2020-08-09 22:20:16 +03:00
static void plot_hexline ( char * scaled_hexagon , int hexagon_size , float start_x , float start_y , float end_x , float end_y ) {
2016-10-27 19:50:10 +03:00
/* Draw a straight line from start to end */
int i ;
2020-08-09 22:20:16 +03:00
float inc_x , inc_y ;
2017-10-23 22:37:52 +03:00
2016-10-27 19:50:10 +03:00
inc_x = ( end_x - start_x ) / hexagon_size ;
inc_y = ( end_y - start_y ) / hexagon_size ;
2017-10-23 22:37:52 +03:00
2016-10-27 19:50:10 +03:00
for ( i = 0 ; i < hexagon_size ; i + + ) {
2020-08-09 22:20:16 +03:00
float this_x = start_x + ( i * inc_x ) ;
float this_y = start_y + ( i * inc_y ) ;
2016-10-27 19:50:10 +03:00
if ( ( ( this_x > = 0 ) & & ( this_x < hexagon_size ) ) & & ( ( this_y > = 0 ) & & ( this_y < hexagon_size ) ) ) {
2020-01-06 23:01:48 +03:00
scaled_hexagon [ ( hexagon_size * ( int ) this_y ) + ( int ) this_x ] = DEFAULT_INK ;
2016-10-27 19:50:10 +03:00
}
}
}
2019-12-19 03:37:55 +03:00
static void plot_hexagon ( char * scaled_hexagon , int hexagon_size ) {
2016-10-27 19:50:10 +03:00
/* Create a hexagon shape and fill it */
int line , i ;
2017-10-23 22:37:52 +03:00
2020-08-09 22:20:16 +03:00
float x_offset [ 6 ] ;
float y_offset [ 6 ] ;
float start_x , start_y ;
float end_x , end_y ;
x_offset [ 0 ] = 0.0f ;
x_offset [ 1 ] = 0.86f ;
x_offset [ 2 ] = 0.86f ;
x_offset [ 3 ] = 0.0f ;
x_offset [ 4 ] = - 0.86f ;
x_offset [ 5 ] = - 0.86f ;
y_offset [ 0 ] = 1.0f ;
y_offset [ 1 ] = 0.5f ;
y_offset [ 2 ] = - 0.5f ;
y_offset [ 3 ] = - 1.0f ;
y_offset [ 4 ] = - 0.5f ;
y_offset [ 5 ] = 0.5f ;
2017-10-23 22:37:52 +03:00
2016-10-27 19:50:10 +03:00
/* Plot hexagon outline */
for ( line = 0 ; line < 5 ; line + + ) {
2020-08-09 22:20:16 +03:00
start_x = ( hexagon_size / 2.0f ) + ( ( hexagon_size / 2.0f ) * x_offset [ line ] ) ;
start_y = ( hexagon_size / 2.0f ) + ( ( hexagon_size / 2.0f ) * y_offset [ line ] ) ;
end_x = ( hexagon_size / 2.0f ) + ( ( hexagon_size / 2.0f ) * x_offset [ line + 1 ] ) ;
end_y = ( hexagon_size / 2.0f ) + ( ( hexagon_size / 2.0f ) * y_offset [ line + 1 ] ) ;
2016-10-27 19:50:10 +03:00
plot_hexline ( scaled_hexagon , hexagon_size , start_x , start_y , end_x , end_y ) ;
}
2020-08-09 22:20:16 +03:00
start_x = ( hexagon_size / 2.0f ) + ( ( hexagon_size / 2.0f ) * x_offset [ line ] ) ;
start_y = ( hexagon_size / 2.0f ) + ( ( hexagon_size / 2.0f ) * y_offset [ line ] ) ;
end_x = ( hexagon_size / 2.0f ) + ( ( hexagon_size / 2.0f ) * x_offset [ 0 ] ) ;
end_y = ( hexagon_size / 2.0f ) + ( ( hexagon_size / 2.0f ) * y_offset [ 0 ] ) ;
2016-10-27 19:50:10 +03:00
plot_hexline ( scaled_hexagon , hexagon_size , start_x , start_y , end_x , end_y ) ;
2017-10-23 22:37:52 +03:00
2016-10-27 19:50:10 +03:00
/* Fill hexagon */
for ( line = 0 ; line < hexagon_size ; line + + ) {
2020-01-06 23:01:48 +03:00
char ink = DEFAULT_PAPER ;
2016-10-27 19:50:10 +03:00
for ( i = 0 ; i < hexagon_size ; i + + ) {
2020-01-06 23:01:48 +03:00
if ( scaled_hexagon [ ( hexagon_size * line ) + i ] = = DEFAULT_INK ) {
2016-10-27 19:50:10 +03:00
if ( i < ( hexagon_size / 2 ) ) {
2020-01-06 23:01:48 +03:00
ink = DEFAULT_INK ;
2016-10-27 19:50:10 +03:00
} else {
2020-01-06 23:01:48 +03:00
ink = DEFAULT_PAPER ;
2016-10-27 19:50:10 +03:00
}
}
2017-10-23 22:37:52 +03:00
2020-01-06 23:01:48 +03:00
if ( ink = = DEFAULT_INK ) {
2016-10-27 19:50:10 +03:00
scaled_hexagon [ ( hexagon_size * line ) + i ] = ink ;
}
}
}
}
2019-12-19 03:37:55 +03:00
static int plot_raster_maxicode ( struct zint_symbol * symbol , int rotate_angle , int data_type ) {
2016-10-27 19:50:10 +03:00
/* Plot a MaxiCode symbol with hexagons and bullseye */
2020-05-21 20:22:28 +03:00
int row , column , xposn ;
2016-07-20 01:02:39 +03:00
int image_height , image_width ;
char * pixelbuf ;
int error_number ;
int xoffset , yoffset ;
2020-05-21 20:22:28 +03:00
int roffset , boffset ;
2020-08-09 22:20:16 +03:00
float scaler = symbol - > scale ;
2016-10-27 19:50:10 +03:00
char * scaled_hexagon ;
int hexagon_size ;
2017-10-23 22:37:52 +03:00
2020-08-10 21:40:10 +03:00
if ( scaler < 0.5f ) {
2020-08-09 22:20:16 +03:00
scaler = 0.5f ;
2020-05-21 20:22:28 +03:00
}
2020-07-15 21:00:12 +03:00
output_set_whitespace_offsets ( symbol , & xoffset , & yoffset , & roffset , & boffset ) ;
2020-05-21 20:22:28 +03:00
2020-07-15 21:00:12 +03:00
image_width = ceil ( ( 300 + 2 * ( xoffset + roffset ) ) * scaler ) ;
image_height = ceil ( ( 300 + 2 * ( yoffset + boffset ) ) * scaler ) ;
2016-07-20 01:02:39 +03:00
if ( ! ( pixelbuf = ( char * ) malloc ( image_width * image_height ) ) ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 655: Insufficient memory for pixel buffer " ) ;
2016-07-20 01:02:39 +03:00
return ZINT_ERROR_ENCODING_PROBLEM ;
}
2020-05-21 20:22:28 +03:00
memset ( pixelbuf , DEFAULT_PAPER , image_width * image_height ) ;
2017-10-23 22:37:52 +03:00
2020-07-15 21:00:12 +03:00
hexagon_size = ceil ( scaler * 10 ) ;
2017-10-23 22:37:52 +03:00
2016-10-27 19:50:10 +03:00
if ( ! ( scaled_hexagon = ( char * ) malloc ( hexagon_size * hexagon_size ) ) ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 656: Insufficient memory for pixel buffer " ) ;
2017-06-28 22:46:29 +03:00
free ( pixelbuf ) ;
2016-10-27 19:50:10 +03:00
return ZINT_ERROR_ENCODING_PROBLEM ;
}
2020-05-21 20:22:28 +03:00
memset ( scaled_hexagon , DEFAULT_PAPER , hexagon_size * hexagon_size ) ;
2017-10-23 22:37:52 +03:00
2016-10-27 19:50:10 +03:00
plot_hexagon ( scaled_hexagon , hexagon_size ) ;
2016-07-20 01:02:39 +03:00
for ( row = 0 ; row < symbol - > rows ; row + + ) {
2017-09-10 18:03:09 +03:00
int yposn = row * 9 ;
2016-07-20 01:02:39 +03:00
for ( column = 0 ; column < symbol - > width ; column + + ) {
xposn = column * 10 ;
if ( module_is_set ( symbol , row , column ) ) {
if ( row & 1 ) {
/* Odd (reduced) row */
xposn + = 5 ;
2016-10-27 19:50:10 +03:00
draw_hexagon ( pixelbuf , image_width , scaled_hexagon , hexagon_size , ( xposn + ( 2 * xoffset ) ) * scaler , ( yposn + ( 2 * yoffset ) ) * scaler ) ;
2016-07-20 01:02:39 +03:00
} else {
/* Even (full) row */
2016-10-27 19:50:10 +03:00
draw_hexagon ( pixelbuf , image_width , scaled_hexagon , hexagon_size , ( xposn + ( 2 * xoffset ) ) * scaler , ( yposn + ( 2 * yoffset ) ) * scaler ) ;
2016-07-20 01:02:39 +03:00
}
}
}
}
2017-10-23 22:37:52 +03:00
2020-08-09 22:20:16 +03:00
draw_bullseye ( pixelbuf , image_width , image_height , ( 2 * xoffset ) , ( 2 * yoffset ) , scaler * 10 ) ;
2017-10-23 22:37:52 +03:00
2017-10-09 13:17:11 +03:00
// Virtual hexagon
//draw_hexagon(pixelbuf, image_width, scaled_hexagon, hexagon_size, ((14 * 10) + (2 * xoffset)) * scaler, ((16 * 9) + (2 * yoffset)) * scaler);
2017-10-23 22:37:52 +03:00
2020-08-01 00:56:41 +03:00
if ( symbol - > border_width > 0 ) {
if ( ( symbol - > output_options & BARCODE_BOX ) | | ( symbol - > output_options & BARCODE_BIND ) ) {
/* boundary bars */
draw_bar ( pixelbuf , 0 , image_width , 0 , symbol - > border_width * 2 , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , 0 , image_width , 300 + ( symbol - > border_width * 2 ) , symbol - > border_width * 2 , image_width , image_height , DEFAULT_INK ) ;
}
2016-07-20 01:02:39 +03:00
2020-08-01 00:56:41 +03:00
if ( symbol - > output_options & BARCODE_BOX ) {
/* side bars */
draw_bar ( pixelbuf , 0 , symbol - > border_width * 2 , 0 , image_height , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , 300 + ( ( symbol - > border_width + symbol - > whitespace_width + symbol - > whitespace_width ) * 2 ) , symbol - > border_width * 2 , 0 , image_height , image_width , image_height , DEFAULT_INK ) ;
}
2016-07-20 01:02:39 +03:00
}
2016-10-27 19:50:10 +03:00
error_number = save_raster_image_to_file ( symbol , image_height , image_width , pixelbuf , rotate_angle , data_type ) ;
free ( scaled_hexagon ) ;
2016-07-20 01:02:39 +03:00
free ( pixelbuf ) ;
return error_number ;
}
2019-12-19 03:37:55 +03:00
static int plot_raster_dotty ( struct zint_symbol * symbol , int rotate_angle , int data_type ) {
2020-08-09 22:20:16 +03:00
float scaler = 2 * symbol - > scale ;
float half_scaler , dot_size_scaled ;
2016-08-09 01:18:55 +03:00
char * scaled_pixelbuf ;
int r , i ;
int scale_width , scale_height ;
int error_number = 0 ;
int xoffset , yoffset , image_width , image_height ;
2020-05-21 20:22:28 +03:00
int roffset , boffset ;
2016-08-09 01:18:55 +03:00
symbol - > height = symbol - > rows ; // This is true because only 2d matrix symbols are processed here
2020-07-15 21:00:12 +03:00
output_set_whitespace_offsets ( symbol , & xoffset , & yoffset , & roffset , & boffset ) ;
2020-05-21 20:22:28 +03:00
image_width = symbol - > width + xoffset + roffset ;
image_height = symbol - > height + yoffset + boffset ;
2016-08-09 01:18:55 +03:00
2020-08-09 22:20:16 +03:00
if ( scaler < 2.0f ) {
scaler = 2.0f ;
2016-08-09 01:18:55 +03:00
}
scale_width = ( image_width * scaler ) + 1 ;
scale_height = ( image_height * scaler ) + 1 ;
/* Apply scale options by creating another pixel buffer */
if ( ! ( scaled_pixelbuf = ( char * ) malloc ( scale_width * scale_height ) ) ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 657: Insufficient memory for pixel buffer " ) ;
2016-08-09 01:18:55 +03:00
return ZINT_ERROR_ENCODING_PROBLEM ;
}
2020-05-21 20:22:28 +03:00
memset ( scaled_pixelbuf , DEFAULT_PAPER , scale_width * scale_height ) ;
2016-08-09 01:18:55 +03:00
/* Plot the body of the symbol to the pixel buffer */
2020-08-09 22:20:16 +03:00
half_scaler = scaler / 2.0f ;
dot_size_scaled = ( symbol - > dot_size * scaler ) / 2.0f ;
2016-08-09 01:18:55 +03:00
for ( r = 0 ; r < symbol - > rows ; r + + ) {
2020-08-09 22:20:16 +03:00
float row_scaled = ( r + yoffset ) * scaler + half_scaler ;
2016-08-09 01:18:55 +03:00
for ( i = 0 ; i < symbol - > width ; i + + ) {
if ( module_is_set ( symbol , r , i ) ) {
draw_circle ( scaled_pixelbuf , scale_width , scale_height ,
2020-07-15 21:00:12 +03:00
( i + xoffset ) * scaler + half_scaler ,
row_scaled ,
dot_size_scaled ,
2020-01-06 23:01:48 +03:00
DEFAULT_INK ) ;
2016-08-09 01:18:55 +03:00
}
}
}
error_number = save_raster_image_to_file ( symbol , scale_height , scale_width , scaled_pixelbuf , rotate_angle , data_type ) ;
free ( scaled_pixelbuf ) ;
return error_number ;
}
2020-07-19 02:13:03 +03:00
/* Convert UTF-8 to ISO 8859-1 for draw_string() human readable text */
static void to_iso8859_1 ( const unsigned char source [ ] , unsigned char preprocessed [ ] ) {
2020-07-18 11:15:54 +03:00
int j , i , input_length ;
input_length = ustrlen ( source ) ;
j = 0 ;
i = 0 ;
while ( i < input_length ) {
switch ( source [ i ] ) {
case 0xC2 :
/* UTF-8 C2xxh */
/* Character range: C280h (latin: 80h) to C2BFh (latin: BFh) */
2020-07-19 12:31:12 +03:00
assert ( i + 1 < input_length ) ;
2020-07-18 11:15:54 +03:00
i + + ;
preprocessed [ j ] = source [ i ] ;
j + + ;
break ;
case 0xC3 :
/* UTF-8 C3xx */
/* Character range: C380h (latin: C0h) to C3BFh (latin: FFh) */
2020-07-19 12:31:12 +03:00
assert ( i + 1 < input_length ) ;
2020-07-18 11:15:54 +03:00
i + + ;
preprocessed [ j ] = source [ i ] + 64 ;
j + + ;
break ;
default :
/* Process ASCII (< 80h), all other unicode points are ignored */
if ( source [ i ] < 128 ) {
preprocessed [ j ] = source [ i ] ;
j + + ;
}
break ;
}
i + + ;
}
preprocessed [ j ] = ' \0 ' ;
return ;
}
2019-12-19 03:37:55 +03:00
static int plot_raster_default ( struct zint_symbol * symbol , int rotate_angle , int data_type ) {
2016-07-20 01:02:39 +03:00
int error_number ;
2020-08-09 22:20:16 +03:00
float large_bar_height ;
2020-07-15 21:00:12 +03:00
int textdone ;
int main_width , comp_offset , addon_gap ;
unsigned char addon [ 6 ] ;
int xoffset , yoffset , roffset , boffset ;
2020-08-09 22:20:16 +03:00
float addon_text_posn ;
2020-07-15 21:00:12 +03:00
int textoffset ;
2016-07-20 01:02:39 +03:00
int default_text_posn ;
2020-08-09 22:20:16 +03:00
float row_height , row_posn ;
2020-07-15 21:00:12 +03:00
int upceanflag = 0 ;
int addon_latch = 0 ;
unsigned char textpart1 [ 5 ] , textpart2 [ 7 ] , textpart3 [ 7 ] , textpart4 [ 2 ] ;
int textpos ;
int hide_text = 0 ;
int i , r ;
int textflags = 0 ;
int image_width , image_height ;
char * pixelbuf ;
2016-07-20 01:02:39 +03:00
int next_yposn ;
2020-07-15 21:00:12 +03:00
int latch ;
int block_width ;
2020-08-09 22:20:16 +03:00
float scaler = symbol - > scale ;
2020-08-10 21:40:10 +03:00
int si ;
int half_int_scaling ;
2020-07-15 21:00:12 +03:00
int scale_width , scale_height ;
2016-08-09 01:18:55 +03:00
char * scaled_pixelbuf ;
int horiz , vert ;
2016-07-20 01:02:39 +03:00
2020-08-10 21:40:10 +03:00
/* Ignore scaling < 0.5 for raster as would drop modules */
if ( scaler < 0.5f ) {
scaler = 0.5f ;
}
/* If half-integer scaling, then set integer scaler `si` to avoid scaling at end */
half_int_scaling = scaler * 2.0f = = ( int ) ( scaler * 2.0f ) ;
if ( half_int_scaling ) {
si = ( int ) ( scaler * 2.0f ) ;
} else {
si = 2 ;
}
2020-07-15 21:00:12 +03:00
large_bar_height = output_large_bar_height ( symbol ) ;
2016-07-20 01:02:39 +03:00
textdone = 0 ;
2020-07-15 21:00:12 +03:00
2016-07-20 01:02:39 +03:00
main_width = symbol - > width ;
comp_offset = 0 ;
2020-07-15 21:00:12 +03:00
if ( is_extendable ( symbol - > symbology ) ) {
upceanflag = output_process_upcean ( symbol , & main_width , & comp_offset , addon , & addon_gap ) ;
2016-07-20 01:02:39 +03:00
}
2020-07-15 21:00:12 +03:00
output_set_whitespace_offsets ( symbol , & xoffset , & yoffset , & roffset , & boffset ) ;
2016-07-20 01:02:39 +03:00
2020-08-09 22:20:16 +03:00
addon_text_posn = 0.0f ;
2020-07-15 21:00:12 +03:00
hide_text = ( ( ! symbol - > show_hrt ) | | ( ustrlen ( symbol - > text ) = = 0 ) ) ;
2016-07-20 01:02:39 +03:00
2020-07-15 21:00:12 +03:00
if ( symbol - > output_options & SMALL_TEXT ) {
textflags = 1 ;
} else if ( symbol - > output_options & BOLD_TEXT ) {
textflags = 2 ;
2016-07-20 01:02:39 +03:00
}
2020-07-15 21:00:12 +03:00
if ( ustrlen ( symbol - > text ) ! = 0 ) {
2016-07-20 01:02:39 +03:00
textoffset = 9 ;
} else {
textoffset = 0 ;
}
2016-08-09 01:18:55 +03:00
2020-08-10 21:40:10 +03:00
image_width = ( symbol - > width + xoffset + roffset ) * si ;
image_height = ( symbol - > height + textoffset + yoffset + boffset ) * si ;
2016-07-20 01:02:39 +03:00
if ( ! ( pixelbuf = ( char * ) malloc ( image_width * image_height ) ) ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 658: Insufficient memory for pixel buffer " ) ;
2016-07-20 01:02:39 +03:00
return ZINT_ERROR_ENCODING_PROBLEM ;
}
2020-05-21 20:22:28 +03:00
memset ( pixelbuf , DEFAULT_PAPER , image_width * image_height ) ;
2016-07-20 01:02:39 +03:00
2020-05-23 02:31:22 +03:00
default_text_posn = image_height - 17 ;
2016-07-20 01:02:39 +03:00
2020-08-09 22:20:16 +03:00
row_height = 0.0f ;
2016-07-20 01:02:39 +03:00
row_posn = textoffset + yoffset ;
next_yposn = textoffset + yoffset ;
/* Plot the body of the symbol to the pixel buffer */
for ( r = 0 ; r < symbol - > rows ; r + + ) {
2017-10-23 22:34:31 +03:00
int plot_yposn ;
int plot_height ;
2017-09-10 18:03:09 +03:00
int this_row = symbol - > rows - r - 1 ; /* invert r otherwise plots upside down */
2020-01-06 23:01:48 +03:00
int module_fill ;
2016-07-20 01:02:39 +03:00
row_posn + = row_height ;
2017-10-16 20:26:54 +03:00
plot_yposn = next_yposn ;
2016-07-20 01:02:39 +03:00
if ( symbol - > row_height [ this_row ] = = 0 ) {
row_height = large_bar_height ;
} else {
row_height = symbol - > row_height [ this_row ] ;
}
next_yposn = ( int ) ( row_posn + row_height ) ;
2017-10-16 20:26:54 +03:00
plot_height = next_yposn - plot_yposn ;
2016-07-20 01:02:39 +03:00
i = 0 ;
do {
2020-01-06 23:01:48 +03:00
module_fill = module_is_set ( symbol , this_row , i ) ;
2016-07-20 01:02:39 +03:00
block_width = 0 ;
do {
block_width + + ;
2019-12-19 03:59:51 +03:00
} while ( ( i + block_width < symbol - > width ) & & module_is_set ( symbol , this_row , i + block_width ) = = module_is_set ( symbol , this_row , i ) ) ;
2020-04-06 19:05:22 +03:00
2016-07-20 01:02:39 +03:00
if ( ( addon_latch = = 0 ) & & ( r = = 0 ) & & ( i > main_width ) ) {
2020-07-15 21:00:12 +03:00
if ( upceanflag = = 12 | | upceanflag = = 6 ) { /* UPC-A/E add-ons don't descend */
2020-08-09 22:20:16 +03:00
plot_height = row_height > 8.0f ? row_height - 8.0f : 1 ;
2020-07-15 21:00:12 +03:00
plot_yposn = row_posn ;
} else {
2020-08-09 22:20:16 +03:00
plot_height = row_height > 3.0f ? row_height - 3.0f : 1 ;
plot_yposn = row_posn - 5.0f ;
2020-07-15 21:00:12 +03:00
}
2016-07-20 01:02:39 +03:00
addon_latch = 1 ;
}
2020-01-06 23:01:48 +03:00
if ( module_fill ) {
2016-07-20 01:02:39 +03:00
/* a bar */
2020-01-06 23:01:48 +03:00
if ( symbol - > symbology = = BARCODE_ULTRA ) {
2020-08-10 21:40:10 +03:00
draw_bar ( pixelbuf , ( i + xoffset ) * si , block_width * si , plot_yposn * si , plot_height * si , image_width , image_height , ultra_colour [ module_fill ] ) ;
2020-01-06 23:01:48 +03:00
} else {
2020-08-10 21:40:10 +03:00
draw_bar ( pixelbuf , ( i + xoffset ) * si , block_width * si , plot_yposn * si , plot_height * si , image_width , image_height , DEFAULT_INK ) ;
2020-01-06 23:01:48 +03:00
}
2016-07-20 01:02:39 +03:00
}
i + = block_width ;
} while ( i < symbol - > width ) ;
}
xoffset + = comp_offset ;
2020-07-15 21:00:12 +03:00
if ( upceanflag ) {
/* Guard bar extension */
if ( upceanflag = = 6 ) { /* UPC-E */
2020-08-10 21:40:10 +03:00
draw_bar ( pixelbuf , ( 0 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , ( 2 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , ( 46 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , ( 48 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , ( 50 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
2020-07-15 21:00:12 +03:00
} else if ( upceanflag = = 8 ) { /* EAN-8 */
2020-08-10 21:40:10 +03:00
draw_bar ( pixelbuf , ( 0 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , ( 2 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , ( 32 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , ( 34 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , ( 64 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , ( 66 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
2020-07-15 21:00:12 +03:00
} else if ( upceanflag = = 12 ) { /* UPC-A */
latch = 1 ;
i = 0 + comp_offset ;
do {
block_width = 0 ;
do {
block_width + + ;
} while ( ( i + block_width < symbol - > width ) & & module_is_set ( symbol , symbol - > rows - 1 , i + block_width ) = = module_is_set ( symbol , symbol - > rows - 1 , i ) ) ;
if ( latch = = 1 ) {
/* a bar */
2020-08-10 21:40:10 +03:00
draw_bar ( pixelbuf , ( i + xoffset - comp_offset ) * si , block_width * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
2020-07-15 21:00:12 +03:00
latch = 0 ;
} else {
/* a space */
latch = 1 ;
2016-07-20 01:02:39 +03:00
}
2020-07-15 21:00:12 +03:00
i + = block_width ;
} while ( i < 11 + comp_offset ) ;
2020-08-10 21:40:10 +03:00
draw_bar ( pixelbuf , ( 46 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , ( 48 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
2020-07-15 21:00:12 +03:00
latch = 1 ;
i = 85 + comp_offset ;
do {
block_width = 0 ;
do {
block_width + + ;
} while ( ( i + block_width < symbol - > width ) & & module_is_set ( symbol , symbol - > rows - 1 , i + block_width ) = = module_is_set ( symbol , symbol - > rows - 1 , i ) ) ;
if ( latch = = 1 ) {
/* a bar */
2020-08-10 21:40:10 +03:00
draw_bar ( pixelbuf , ( i + xoffset - comp_offset ) * si , block_width * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
2020-07-15 21:00:12 +03:00
latch = 0 ;
} else {
/* a space */
latch = 1 ;
}
i + = block_width ;
} while ( i < 96 + comp_offset ) ;
} else if ( upceanflag = = 13 ) { /* EAN-13 */
2020-08-10 21:40:10 +03:00
draw_bar ( pixelbuf , ( 0 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , ( 2 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , ( 46 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , ( 48 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , ( 92 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , ( 94 + xoffset ) * si , 1 * si , ( 4 + yoffset ) * si , 5 * si , image_width , image_height , DEFAULT_INK ) ;
2020-07-15 21:00:12 +03:00
}
}
if ( ! hide_text ) {
2016-07-20 01:02:39 +03:00
2020-07-15 21:00:12 +03:00
if ( upceanflag ) {
output_upcean_split_text ( upceanflag , symbol - > text , textpart1 , textpart2 , textpart3 , textpart4 ) ;
if ( upceanflag = = 6 ) { /* UPC-E */
2020-08-10 21:40:10 +03:00
textpos = ( - 5 + xoffset ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , textpart1 , textpos , default_text_posn , textflags , image_width , image_height ) ;
2020-08-10 21:40:10 +03:00
textpos = ( 24 + xoffset ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , textpart2 , textpos , default_text_posn , textflags , image_width , image_height ) ;
2020-08-10 21:40:10 +03:00
textpos = ( 55 + xoffset ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , textpart3 , textpos , default_text_posn , textflags , image_width , image_height ) ;
textdone = 1 ;
switch ( ustrlen ( addon ) ) {
case 2 :
2020-08-10 21:40:10 +03:00
textpos = ( 61 + xoffset + addon_gap ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , addon , textpos , addon_text_posn , textflags , image_width , image_height ) ;
break ;
case 5 :
2020-08-10 21:40:10 +03:00
textpos = ( 75 + xoffset + addon_gap ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , addon , textpos , addon_text_posn , textflags , image_width , image_height ) ;
break ;
2016-07-20 01:02:39 +03:00
}
2020-07-15 21:00:12 +03:00
} else if ( upceanflag = = 8 ) { /* EAN-8 */
2020-08-10 21:40:10 +03:00
textpos = ( 17 + xoffset ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , textpart1 , textpos , default_text_posn , textflags , image_width , image_height ) ;
2020-08-10 21:40:10 +03:00
textpos = ( 50 + xoffset ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , textpart2 , textpos , default_text_posn , textflags , image_width , image_height ) ;
2016-07-20 01:02:39 +03:00
textdone = 1 ;
2020-07-15 21:00:12 +03:00
switch ( ustrlen ( addon ) ) {
2016-07-20 01:02:39 +03:00
case 2 :
2020-08-10 21:40:10 +03:00
textpos = ( 77 + xoffset + addon_gap ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , addon , textpos , addon_text_posn , textflags , image_width , image_height ) ;
2016-07-20 01:02:39 +03:00
break ;
case 5 :
2020-08-10 21:40:10 +03:00
textpos = ( 91 + xoffset + addon_gap ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , addon , textpos , addon_text_posn , textflags , image_width , image_height ) ;
2016-07-20 01:02:39 +03:00
break ;
}
2020-07-15 21:00:12 +03:00
} else if ( upceanflag = = 12 ) { /* UPC-A */
2020-08-10 21:40:10 +03:00
textpos = ( - 5 + xoffset ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , textpart1 , textpos , default_text_posn , textflags , image_width , image_height ) ;
2020-08-10 21:40:10 +03:00
textpos = ( 27 + xoffset ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , textpart2 , textpos , default_text_posn , textflags , image_width , image_height ) ;
2020-08-10 21:40:10 +03:00
textpos = ( 68 + xoffset ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , textpart3 , textpos , default_text_posn , textflags , image_width , image_height ) ;
2020-08-10 21:40:10 +03:00
textpos = ( 100 + xoffset ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , textpart4 , textpos , default_text_posn , textflags , image_width , image_height ) ;
textdone = 1 ;
switch ( ustrlen ( addon ) ) {
case 2 :
2020-08-10 21:40:10 +03:00
textpos = ( 107 + xoffset + addon_gap ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , addon , textpos , addon_text_posn , textflags , image_width , image_height ) ;
break ;
case 5 :
2020-08-10 21:40:10 +03:00
textpos = ( 121 + xoffset + addon_gap ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , addon , textpos , addon_text_posn , textflags , image_width , image_height ) ;
break ;
2016-07-20 01:02:39 +03:00
}
2020-07-15 21:00:12 +03:00
} else if ( upceanflag = = 13 ) { /* EAN-13 */
2020-08-10 21:40:10 +03:00
textpos = ( - 7 + xoffset ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , textpart1 , textpos , default_text_posn , textflags , image_width , image_height ) ;
2020-08-10 21:40:10 +03:00
textpos = ( 24 + xoffset ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , textpart2 , textpos , default_text_posn , textflags , image_width , image_height ) ;
2020-08-10 21:40:10 +03:00
textpos = ( 71 + xoffset ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , textpart3 , textpos , default_text_posn , textflags , image_width , image_height ) ;
2016-07-20 01:02:39 +03:00
textdone = 1 ;
2020-07-15 21:00:12 +03:00
switch ( ustrlen ( addon ) ) {
2016-07-20 01:02:39 +03:00
case 2 :
2020-08-10 21:40:10 +03:00
textpos = ( 105 + xoffset + addon_gap ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , addon , textpos , addon_text_posn , textflags , image_width , image_height ) ;
2016-07-20 01:02:39 +03:00
break ;
case 5 :
2020-08-10 21:40:10 +03:00
textpos = ( 119 + xoffset + addon_gap ) * si ;
2020-07-15 21:00:12 +03:00
draw_string ( pixelbuf , addon , textpos , addon_text_posn , textflags , image_width , image_height ) ;
2016-07-20 01:02:39 +03:00
break ;
}
}
}
2020-07-15 21:00:12 +03:00
if ( ! textdone ) {
2020-07-19 12:31:12 +03:00
unsigned char local_text [ sizeof ( symbol - > text ) ] ;
2020-07-19 02:13:03 +03:00
to_iso8859_1 ( symbol - > text , local_text ) ;
2020-07-15 21:00:12 +03:00
/* Put the human readable text at the bottom */
2020-08-10 21:40:10 +03:00
textpos = ( main_width / 2 + xoffset ) * si ;
2020-07-18 11:15:54 +03:00
draw_string ( pixelbuf , local_text , textpos , default_text_posn , textflags , image_width , image_height ) ;
2016-07-20 01:02:39 +03:00
}
}
xoffset - = comp_offset ;
2020-08-01 00:56:41 +03:00
// Binding and boxes
if ( ( symbol - > output_options & BARCODE_BIND ) ! = 0 ) {
if ( ( symbol - > rows > 1 ) & & ( is_stackable ( symbol - > symbology ) = = 1 ) ) {
2020-08-09 22:20:16 +03:00
float sep_height = 1.0f ;
2020-08-01 00:56:41 +03:00
if ( symbol - > option_3 > 0 & & symbol - > option_3 < = 4 ) {
sep_height = symbol - > option_3 ;
}
/* row binding */
if ( symbol - > symbology ! = BARCODE_CODABLOCKF & & symbol - > symbology ! = BARCODE_HIBC_BLOCKF ) {
for ( r = 1 ; r < symbol - > rows ; r + + ) {
2020-08-10 21:40:10 +03:00
draw_bar ( pixelbuf , xoffset * si , symbol - > width * si ,
( ( r * row_height ) + textoffset + yoffset - sep_height / 2 ) * si , sep_height * si , image_width , image_height , DEFAULT_INK ) ;
2020-05-16 12:22:33 +03:00
}
2020-08-01 00:56:41 +03:00
} else {
for ( r = 1 ; r < symbol - > rows ; r + + ) {
/* Avoid 11-module start and 13-module stop chars */
2020-08-10 21:40:10 +03:00
draw_bar ( pixelbuf , ( xoffset + 11 ) * si , ( symbol - > width - 24 ) * si ,
( ( r * row_height ) + textoffset + yoffset - sep_height / 2 ) * si , sep_height * si , image_width , image_height , DEFAULT_INK ) ;
2016-07-20 01:02:39 +03:00
}
}
}
}
2020-08-01 00:56:41 +03:00
if ( symbol - > border_width > 0 ) {
if ( ( symbol - > output_options & BARCODE_BOX ) | | ( symbol - > output_options & BARCODE_BIND ) ) {
/* boundary bars */
if ( ( symbol - > output_options & BARCODE_BOX ) | | ( symbol - > symbology ! = BARCODE_CODABLOCKF & & symbol - > symbology ! = BARCODE_HIBC_BLOCKF ) ) {
2020-08-10 21:40:10 +03:00
draw_bar ( pixelbuf , 0 , ( symbol - > width + xoffset + roffset ) * si ,
textoffset * si , symbol - > border_width * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , 0 , ( symbol - > width + xoffset + roffset ) * si ,
( textoffset + symbol - > height + symbol - > border_width ) * si , symbol - > border_width * si , image_width , image_height , DEFAULT_INK ) ;
2020-08-01 00:56:41 +03:00
} else {
2020-08-10 21:40:10 +03:00
draw_bar ( pixelbuf , xoffset * si , symbol - > width * si ,
textoffset * si , symbol - > border_width * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , xoffset * si , symbol - > width * si ,
( textoffset + symbol - > height + symbol - > border_width ) * si , symbol - > border_width * si , image_width , image_height , DEFAULT_INK ) ;
2020-08-01 00:56:41 +03:00
}
}
if ( ( symbol - > output_options & BARCODE_BOX ) ) {
/* side bars */
2020-08-10 21:40:10 +03:00
draw_bar ( pixelbuf , 0 , symbol - > border_width * si ,
textoffset * si , ( symbol - > height + ( 2 * symbol - > border_width ) ) * si , image_width , image_height , DEFAULT_INK ) ;
draw_bar ( pixelbuf , ( symbol - > width + xoffset + roffset - symbol - > border_width ) * si , symbol - > border_width * si ,
textoffset * si , ( symbol - > height + ( 2 * symbol - > border_width ) ) * si , image_width , image_height , DEFAULT_INK ) ;
2020-08-01 00:56:41 +03:00
}
2016-07-20 01:02:39 +03:00
}
2020-08-10 21:40:10 +03:00
if ( ! half_int_scaling ) {
2020-05-21 20:22:28 +03:00
scale_width = image_width * scaler ;
scale_height = image_height * scaler ;
/* Apply scale options by creating another pixel buffer */
if ( ! ( scaled_pixelbuf = ( char * ) malloc ( scale_width * scale_height ) ) ) {
free ( pixelbuf ) ;
strcpy ( symbol - > errtxt , " 659: Insufficient memory for pixel buffer " ) ;
return ZINT_ERROR_ENCODING_PROBLEM ;
2016-08-09 01:18:55 +03:00
}
2020-05-21 20:22:28 +03:00
memset ( scaled_pixelbuf , DEFAULT_PAPER , scale_width * scale_height ) ;
2016-08-09 01:18:55 +03:00
2020-05-21 20:22:28 +03:00
for ( vert = 0 ; vert < scale_height ; vert + + ) {
2020-07-20 14:06:14 +03:00
int vert_row = vert * scale_width ;
int image_vert_row = ( ( int ) ( vert / scaler ) ) * image_width ;
2020-05-21 20:22:28 +03:00
for ( horiz = 0 ; horiz < scale_width ; horiz + + ) {
2020-07-20 14:06:14 +03:00
* ( scaled_pixelbuf + vert_row + horiz ) = * ( pixelbuf + image_vert_row + ( int ) ( horiz / scaler ) ) ;
2020-05-21 20:22:28 +03:00
}
2016-08-09 01:18:55 +03:00
}
2020-05-21 20:22:28 +03:00
error_number = save_raster_image_to_file ( symbol , scale_height , scale_width , scaled_pixelbuf , rotate_angle , data_type ) ;
free ( scaled_pixelbuf ) ;
} else {
error_number = save_raster_image_to_file ( symbol , image_height , image_width , pixelbuf , rotate_angle , data_type ) ;
}
2016-07-20 01:02:39 +03:00
free ( pixelbuf ) ;
return error_number ;
}
2019-12-19 03:37:55 +03:00
INTERNAL int plot_raster ( struct zint_symbol * symbol , int rotate_angle , int file_type ) {
2016-07-20 01:02:39 +03:00
int error ;
# ifdef NO_PNG
2020-05-21 20:22:28 +03:00
if ( file_type = = OUT_PNG_FILE ) {
strcpy ( symbol - > errtxt , " 660: PNG format disabled at compile time " ) ;
2016-07-20 01:02:39 +03:00
return ZINT_ERROR_INVALID_OPTION ;
}
2017-10-23 22:37:52 +03:00
# endif /* NO_PNG */
2016-08-09 01:18:55 +03:00
2020-07-15 21:00:12 +03:00
error = output_check_colour_options ( symbol ) ;
2020-05-21 20:22:28 +03:00
if ( error ! = 0 ) {
return error ;
}
2016-08-26 17:13:40 +03:00
if ( symbol - > output_options & BARCODE_DOTTY_MODE ) {
2016-08-09 01:18:55 +03:00
error = plot_raster_dotty ( symbol , rotate_angle , file_type ) ;
2016-07-20 01:02:39 +03:00
} else {
2016-08-09 01:18:55 +03:00
if ( symbol - > symbology = = BARCODE_MAXICODE ) {
error = plot_raster_maxicode ( symbol , rotate_angle , file_type ) ;
} else {
error = plot_raster_default ( symbol , rotate_angle , file_type ) ;
}
2016-07-20 01:02:39 +03:00
}
return error ;
}