2008-07-14 01:15:55 +04:00
/* ps.c - Post Script output */
/*
libzint - the open source barcode library
2018-06-10 11:16:18 +03:00
Copyright ( C ) 2009 - 2018 Robin Stuart < rstuart114 @ gmail . com >
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 :
2016-02-20 14:29:19 +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 14:29:19 +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 14:29:19 +03:00
without specific prior written permission .
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 14:29:19 +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 14:29:19 +03:00
*/
2019-12-19 03:37:55 +03:00
/* vim: set ts=4 sw=4 et : */
2008-07-14 01:15:55 +04:00
2010-05-23 09:02:08 +04:00
# include <locale.h>
2008-07-14 01:15:55 +04:00
# include <string.h>
# include <stdlib.h>
# include <stdio.h>
2016-03-03 00:12:38 +03:00
# include <math.h>
2008-07-14 01:15:55 +04:00
# include "common.h"
2020-01-06 21:00:43 +03:00
void colour_to_pscolor ( int option , int colour , char * output ) {
strcpy ( output , " " ) ;
if ( ( option & CMYK_COLOUR ) = = 0 ) {
// Use RGB colour space
switch ( colour ) {
case 0 : // White
strcat ( output , " 1.00 1.00 1.00 " ) ;
break ;
case 1 : // Cyan
strcat ( output , " 0.00 1.00 1.00 " ) ;
break ;
case 2 : // Blue
strcat ( output , " 0.00 0.00 1.00 " ) ;
break ;
case 3 : // Magenta
strcat ( output , " 1.00 0.00 1.00 " ) ;
break ;
case 4 : // Red
strcat ( output , " 1.00 0.00 0.00 " ) ;
break ;
case 5 : // Yellow
strcat ( output , " 1.00 1.00 0.00 " ) ;
break ;
case 6 : // Green
strcat ( output , " 0.00 1.00 0.00 " ) ;
break ;
default : // Black
strcat ( output , " 0.00 0.00 0.00 " ) ;
break ;
}
strcat ( output , " setrgbcolor " ) ;
} else {
// Use CMYK colour space
switch ( colour ) {
case 0 : // White
strcat ( output , " 0.00 0.00 0.00 0.00 " ) ;
break ;
case 1 : // Cyan
strcat ( output , " 1.00 0.00 0.00 0.00 " ) ;
break ;
case 2 : // Blue
strcat ( output , " 1.00 1.00 0.00 0.00 " ) ;
break ;
case 3 : // Magenta
strcat ( output , " 0.00 1.00 0.00 0.00 " ) ;
break ;
case 4 : // Red
strcat ( output , " 0.00 1.00 1.00 0.00 " ) ;
break ;
case 5 : // Yellow
strcat ( output , " 0.00 0.00 1.00 0.00 " ) ;
break ;
case 6 : // Green
strcat ( output , " 1.00 0.00 1.00 0.00 " ) ;
break ;
default : // Black
strcat ( output , " 0.00 0.00 0.00 1.00 " ) ;
break ;
}
strcat ( output , " setcmykcolor " ) ;
}
}
2019-12-19 03:37:55 +03:00
INTERNAL int ps_plot ( struct zint_symbol * symbol ) {
2016-02-20 14:29:19 +03:00
FILE * feps ;
int fgred , fggrn , fgblu , bgred , bggrn , bgblu ;
float red_ink , green_ink , blue_ink , red_paper , green_paper , blue_paper ;
2016-06-19 16:14:30 +03:00
float cyan_ink , magenta_ink , yellow_ink , black_ink ;
float cyan_paper , magenta_paper , yellow_paper , black_paper ;
2016-02-20 14:29:19 +03:00
int error_number = 0 ;
2018-06-10 11:16:18 +03:00
float ax , ay , bx , by , cx , cy , dx , dy , ex , ey , fx , fy ;
float radius ;
2020-01-06 21:00:43 +03:00
int colour_index , colour_rect_counter ;
char ps_color [ 30 ] ;
2020-01-05 14:27:24 +03:00
2018-06-10 11:16:18 +03:00
struct zint_vector_rect * rect ;
struct zint_vector_hexagon * hex ;
struct zint_vector_circle * circle ;
struct zint_vector_string * string ;
2016-02-20 14:29:19 +03:00
const char * locale = NULL ;
2016-08-26 17:13:40 +03:00
if ( symbol - > output_options & BARCODE_STDOUT ) {
2016-02-20 14:29:19 +03:00
feps = stdout ;
} else {
feps = fopen ( symbol - > outfile , " w " ) ;
}
if ( feps = = NULL ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 645: Could not open output file " ) ;
2016-02-20 14:29:19 +03:00
return ZINT_ERROR_FILE_ACCESS ;
}
locale = setlocale ( LC_ALL , " C " ) ;
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 ] ) ;
red_ink = fgred / 256.0 ;
green_ink = fggrn / 256.0 ;
blue_ink = fgblu / 256.0 ;
red_paper = bgred / 256.0 ;
green_paper = bggrn / 256.0 ;
blue_paper = bgblu / 256.0 ;
2016-09-06 00:06:50 +03:00
2016-06-19 16:14:30 +03:00
/* Convert RGB to CMYK */
if ( red_ink > green_ink ) {
if ( blue_ink > red_ink ) {
black_ink = 1 - blue_ink ;
} else {
black_ink = 1 - red_ink ;
}
} else {
if ( blue_ink > red_ink ) {
black_ink = 1 - blue_ink ;
} else {
black_ink = 1 - green_ink ;
}
}
if ( black_ink < 1.0 ) {
cyan_ink = ( 1 - red_ink - black_ink ) / ( 1 - black_ink ) ;
magenta_ink = ( 1 - green_ink - black_ink ) / ( 1 - black_ink ) ;
yellow_ink = ( 1 - blue_ink - black_ink ) / ( 1 - black_ink ) ;
} else {
cyan_ink = 0.0 ;
magenta_ink = 0.0 ;
yellow_ink = 0.0 ;
}
2016-09-06 00:06:50 +03:00
2016-06-19 16:14:30 +03:00
if ( red_paper > green_paper ) {
if ( blue_paper > red_paper ) {
black_paper = 1 - blue_paper ;
} else {
black_paper = 1 - red_paper ;
}
} else {
if ( blue_paper > red_paper ) {
black_paper = 1 - blue_paper ;
} else {
black_paper = 1 - green_paper ;
}
}
if ( black_paper < 1.0 ) {
cyan_paper = ( 1 - red_paper - black_paper ) / ( 1 - black_paper ) ;
magenta_paper = ( 1 - green_paper - black_paper ) / ( 1 - black_paper ) ;
yellow_paper = ( 1 - blue_paper - black_paper ) / ( 1 - black_paper ) ;
} else {
cyan_paper = 0.0 ;
magenta_paper = 0.0 ;
yellow_paper = 0.0 ;
}
2016-02-20 14:29:19 +03:00
/* Start writing the header */
fprintf ( feps , " %%!PS-Adobe-3.0 EPSF-3.0 \n " ) ;
2016-12-10 12:04:06 +03:00
fprintf ( feps , " %%%%Creator: Zint %d.%d.%d \n " , ZINT_VERSION_MAJOR , ZINT_VERSION_MINOR , ZINT_VERSION_RELEASE ) ;
2018-06-10 11:16:18 +03:00
fprintf ( feps , " %%%%Title: Zint Generated Symbol \n " ) ;
2016-02-20 14:29:19 +03:00
fprintf ( feps , " %%%%Pages: 0 \n " ) ;
2018-06-10 11:16:18 +03:00
fprintf ( feps , " %%%%BoundingBox: 0 0 %d %d \n " , ( int ) ceil ( symbol - > vector - > width ) , ( int ) ceil ( symbol - > vector - > height ) ) ;
2016-02-20 14:29:19 +03:00
fprintf ( feps , " %%%%EndComments \n " ) ;
/* Definitions */
fprintf ( feps , " /TL { setlinewidth moveto lineto stroke } bind def \n " ) ;
2016-08-28 18:38:02 +03:00
fprintf ( feps , " /TD { newpath 0 360 arc fill } bind def \n " ) ;
2016-02-20 14:29:19 +03:00
fprintf ( feps , " /TH { 0 setlinewidth moveto lineto lineto lineto lineto lineto closepath fill } bind def \n " ) ;
fprintf ( feps , " /TB { 2 copy } bind def \n " ) ;
fprintf ( feps , " /TR { newpath 4 1 roll exch moveto 1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath fill } bind def \n " ) ;
fprintf ( feps , " /TE { pop pop } bind def \n " ) ;
fprintf ( feps , " newpath \n " ) ;
/* Now the actual representation */
2016-06-19 16:14:30 +03:00
if ( ( symbol - > output_options & CMYK_COLOUR ) = = 0 ) {
fprintf ( feps , " %.2f %.2f %.2f setrgbcolor \n " , red_paper , green_paper , blue_paper ) ;
} else {
fprintf ( feps , " %.2f %.2f %.2f %.2f setcmykcolor \n " , cyan_paper , magenta_paper , yellow_paper , black_paper ) ;
}
2018-06-10 11:16:18 +03:00
fprintf ( feps , " %.2f 0.00 TB 0.00 %.2f TR \n " , symbol - > vector - > height , symbol - > vector - > width ) ;
2016-02-20 14:29:19 +03:00
2018-06-10 11:16:18 +03:00
fprintf ( feps , " TE \n " ) ;
2020-01-06 21:00:43 +03:00
if ( symbol - > symbology ! = BARCODE_ULTRA ) {
if ( ( symbol - > output_options & CMYK_COLOUR ) = = 0 ) {
fprintf ( feps , " %.2f %.2f %.2f setrgbcolor \n " , red_ink , green_ink , blue_ink ) ;
} else {
fprintf ( feps , " %.2f %.2f %.2f %.2f setcmykcolor \n " , cyan_ink , magenta_ink , yellow_ink , black_ink ) ;
}
2016-02-20 14:29:19 +03:00
}
2020-01-05 14:27:24 +03:00
2018-06-10 11:16:18 +03:00
// Rectangles
2020-01-06 21:00:43 +03:00
if ( symbol - > symbology = = BARCODE_ULTRA ) {
for ( colour_index = 0 ; colour_index < = 7 ; colour_index + + ) {
colour_rect_counter = 0 ;
rect = symbol - > vector - > rectangles ;
while ( rect ) {
if ( rect - > colour = = colour_index ) {
if ( colour_rect_counter = = 0 ) {
//Set new colour
colour_to_pscolor ( symbol - > output_options , colour_index , ps_color ) ;
fprintf ( feps , " %s \n " , ps_color ) ;
}
colour_rect_counter + + ;
fprintf ( feps , " %.2f %.2f TB %.2f %.2f TR \n " , rect - > height , ( symbol - > vector - > height - rect - > y ) - rect - > height , rect - > x , rect - > width ) ;
fprintf ( feps , " TE \n " ) ;
}
rect = rect - > next ;
}
}
} else {
rect = symbol - > vector - > rectangles ;
while ( rect ) {
fprintf ( feps , " %.2f %.2f TB %.2f %.2f TR \n " , rect - > height , ( symbol - > vector - > height - rect - > y ) - rect - > height , rect - > x , rect - > width ) ;
fprintf ( feps , " TE \n " ) ;
rect = rect - > next ;
}
2018-06-10 11:16:18 +03:00
}
2020-01-05 14:27:24 +03:00
2018-06-10 11:16:18 +03:00
// Hexagons
hex = symbol - > vector - > hexagons ;
while ( hex ) {
radius = hex - > diameter / 2.0 ;
ay = ( symbol - > vector - > height - hex - > y ) + ( 1.0 * radius ) ;
by = ( symbol - > vector - > height - hex - > y ) + ( 0.5 * radius ) ;
cy = ( symbol - > vector - > height - hex - > y ) - ( 0.5 * radius ) ;
dy = ( symbol - > vector - > height - hex - > y ) - ( 1.0 * radius ) ;
ey = ( symbol - > vector - > height - hex - > y ) - ( 0.5 * radius ) ;
fy = ( symbol - > vector - > height - hex - > y ) + ( 0.5 * radius ) ;
ax = hex - > x ;
bx = hex - > x + ( 0.86 * radius ) ;
cx = hex - > x + ( 0.86 * radius ) ;
dx = hex - > x ;
ex = hex - > x - ( 0.86 * radius ) ;
fx = hex - > x - ( 0.86 * radius ) ;
fprintf ( feps , " %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f TH \n " , ax , ay , bx , by , cx , cy , dx , dy , ex , ey , fx , fy ) ;
hex = hex - > next ;
}
2020-01-05 14:27:24 +03:00
2018-06-10 11:16:18 +03:00
// Circles
circle = symbol - > vector - > circles ;
while ( circle ) {
if ( circle - > colour ) {
// A 'white' circle
2016-06-19 16:14:30 +03:00
if ( ( symbol - > output_options & CMYK_COLOUR ) = = 0 ) {
2018-06-10 11:16:18 +03:00
fprintf ( feps , " %.2f %.2f %.2f setrgbcolor \n " , red_paper , green_paper , blue_paper ) ;
2016-06-19 16:14:30 +03:00
} else {
2018-06-10 11:16:18 +03:00
fprintf ( feps , " %.2f %.2f %.2f %.2f setcmykcolor \n " , cyan_paper , magenta_paper , yellow_paper , black_paper ) ;
2016-02-20 14:29:19 +03:00
}
2018-06-10 11:16:18 +03:00
fprintf ( feps , " %.2f %.2f %.2f TD \n " , circle - > x , ( symbol - > vector - > height - circle - > y ) , circle - > diameter / 2.0 ) ;
if ( circle - > next ) {
2016-08-28 18:38:02 +03:00
if ( ( symbol - > output_options & CMYK_COLOUR ) = = 0 ) {
fprintf ( feps , " %.2f %.2f %.2f setrgbcolor \n " , red_ink , green_ink , blue_ink ) ;
} else {
fprintf ( feps , " %.2f %.2f %.2f %.2f setcmykcolor \n " , cyan_ink , magenta_ink , yellow_ink , black_ink ) ;
}
}
2016-06-19 16:14:30 +03:00
} else {
2018-06-10 11:16:18 +03:00
// A 'black' circle
fprintf ( feps , " %.2f %.2f %.2f TD \n " , circle - > x , ( symbol - > vector - > height - circle - > y ) , circle - > diameter / 2.0 ) ;
2016-06-19 13:59:09 +03:00
}
2018-06-10 11:16:18 +03:00
circle = circle - > next ;
2016-06-19 13:59:09 +03:00
}
2020-01-05 14:27:24 +03:00
2018-06-10 11:16:18 +03:00
// Text
string = symbol - > vector - > strings ;
while ( string ) {
2016-02-20 14:29:19 +03:00
fprintf ( feps , " matrix currentmatrix \n " ) ;
fprintf ( feps , " /Helvetica findfont \n " ) ;
2018-06-10 11:16:18 +03:00
fprintf ( feps , " %.2f scalefont setfont \n " , string - > fsize ) ;
fprintf ( feps , " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto \n " , string - > x , ( symbol - > vector - > height - string - > y ) ) ;
fprintf ( feps , " (%s) stringwidth \n " , string - > text ) ;
2016-02-20 14:29:19 +03:00
fprintf ( feps , " pop \n " ) ;
fprintf ( feps , " -2 div 0 rmoveto \n " ) ;
2018-06-10 11:16:18 +03:00
fprintf ( feps , " (%s) show \n " , string - > text ) ;
2016-02-20 14:29:19 +03:00
fprintf ( feps , " setmatrix \n " ) ;
2018-06-10 11:16:18 +03:00
string = string - > next ;
2016-02-20 14:29:19 +03:00
}
2020-01-05 14:27:24 +03:00
//fprintf(feps, "\nshowpage\n");
2016-02-20 14:29:19 +03:00
if ( symbol - > output_options & BARCODE_STDOUT ) {
fflush ( feps ) ;
} else {
fclose ( feps ) ;
}
if ( locale )
setlocale ( LC_ALL , locale ) ;
return error_number ;
2008-07-14 01:15:55 +04:00
}