2008-07-14 09:15:55 +12:00
|
|
|
/* ps.c - Post Script output */
|
|
|
|
|
|
|
|
/*
|
|
|
|
libzint - the open source barcode library
|
2018-06-10 20:16:18 +12:00
|
|
|
Copyright (C) 2009-2018 Robin Stuart <rstuart114@gmail.com>
|
2013-05-17 05:26:38 +12:00
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
|
|
|
|
2016-02-21 00:29:19 +13:00
|
|
|
1. Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
2013-05-17 05:26:38 +12:00
|
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
2016-02-21 00:29:19 +13:00
|
|
|
documentation and/or other materials provided with the distribution.
|
2013-05-17 05:26:38 +12: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-21 00:29:19 +13:00
|
|
|
without specific prior written permission.
|
2013-05-17 05:26:38 +12: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-21 00:29:19 +13:00
|
|
|
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
2013-05-17 05:26:38 +12:00
|
|
|
SUCH DAMAGE.
|
2016-02-21 00:29:19 +13:00
|
|
|
*/
|
2019-12-19 13:37:55 +13:00
|
|
|
/* vim: set ts=4 sw=4 et : */
|
2008-07-14 09:15:55 +12:00
|
|
|
|
2010-05-23 17:02:08 +12:00
|
|
|
#include <locale.h>
|
2008-07-14 09:15:55 +12:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
2016-03-03 10:12:38 +13:00
|
|
|
#include <math.h>
|
2008-07-14 09:15:55 +12:00
|
|
|
#include "common.h"
|
|
|
|
|
2020-01-07 07:00:43 +13: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 13:37:55 +13:00
|
|
|
INTERNAL int ps_plot(struct zint_symbol *symbol) {
|
2016-02-21 00:29:19 +13: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-20 01:14:30 +12:00
|
|
|
float cyan_ink, magenta_ink, yellow_ink, black_ink;
|
|
|
|
float cyan_paper, magenta_paper, yellow_paper, black_paper;
|
2016-02-21 00:29:19 +13:00
|
|
|
int error_number = 0;
|
2018-06-10 20:16:18 +12:00
|
|
|
float ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy;
|
|
|
|
float radius;
|
2020-01-07 07:00:43 +13:00
|
|
|
int colour_index, colour_rect_counter;
|
|
|
|
char ps_color[30];
|
2020-08-03 18:37:27 +12:00
|
|
|
int draw_background = 1;
|
|
|
|
|
|
|
|
if (strlen(symbol->bgcolour) > 6) {
|
|
|
|
if ((ctoi(symbol->bgcolour[6]) == 0) && (ctoi(symbol->bgcolour[7]) == 0)) {
|
|
|
|
draw_background = 0;
|
|
|
|
}
|
|
|
|
}
|
2020-01-06 00:27:24 +13:00
|
|
|
|
2018-06-10 20:16:18 +12:00
|
|
|
struct zint_vector_rect *rect;
|
|
|
|
struct zint_vector_hexagon *hex;
|
|
|
|
struct zint_vector_circle *circle;
|
|
|
|
struct zint_vector_string *string;
|
2016-02-21 00:29:19 +13:00
|
|
|
const char *locale = NULL;
|
|
|
|
|
2016-08-27 02:13:40 +12:00
|
|
|
if (symbol->output_options & BARCODE_STDOUT) {
|
2016-02-21 00:29:19 +13:00
|
|
|
feps = stdout;
|
|
|
|
} else {
|
|
|
|
feps = fopen(symbol->outfile, "w");
|
|
|
|
}
|
|
|
|
if (feps == NULL) {
|
2017-07-28 03:01:53 +12:00
|
|
|
strcpy(symbol->errtxt, "645: Could not open output file");
|
2016-02-21 00:29:19 +13: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 09:06:50 +12:00
|
|
|
|
2016-06-20 01:14:30 +12: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 09:06:50 +12:00
|
|
|
|
2016-06-20 01:14:30 +12: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-21 00:29:19 +13:00
|
|
|
|
|
|
|
/* Start writing the header */
|
|
|
|
fprintf(feps, "%%!PS-Adobe-3.0 EPSF-3.0\n");
|
2016-12-10 22:04:06 +13:00
|
|
|
fprintf(feps, "%%%%Creator: Zint %d.%d.%d\n", ZINT_VERSION_MAJOR, ZINT_VERSION_MINOR, ZINT_VERSION_RELEASE);
|
2018-06-10 20:16:18 +12:00
|
|
|
fprintf(feps, "%%%%Title: Zint Generated Symbol\n");
|
2016-02-21 00:29:19 +13:00
|
|
|
fprintf(feps, "%%%%Pages: 0\n");
|
2018-06-10 20:16:18 +12:00
|
|
|
fprintf(feps, "%%%%BoundingBox: 0 0 %d %d\n", (int) ceil(symbol->vector->width), (int) ceil(symbol->vector->height));
|
2016-02-21 00:29:19 +13:00
|
|
|
fprintf(feps, "%%%%EndComments\n");
|
|
|
|
|
|
|
|
/* Definitions */
|
|
|
|
fprintf(feps, "/TL { setlinewidth moveto lineto stroke } bind def\n");
|
2016-08-29 03:38:02 +12:00
|
|
|
fprintf(feps, "/TD { newpath 0 360 arc fill } bind def\n");
|
2016-02-21 00:29:19 +13: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 */
|
2020-08-03 18:37:27 +12:00
|
|
|
|
|
|
|
//Background
|
|
|
|
if (draw_background) {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(feps, "%.2f 0.00 TB 0.00 %.2f TR\n", symbol->vector->height, symbol->vector->width);
|
|
|
|
fprintf(feps, "TE\n");
|
2016-06-20 01:14:30 +12:00
|
|
|
}
|
2016-02-21 00:29:19 +13:00
|
|
|
|
2020-01-07 07:00:43 +13: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-21 00:29:19 +13:00
|
|
|
}
|
2020-01-06 00:27:24 +13:00
|
|
|
|
2018-06-10 20:16:18 +12:00
|
|
|
// Rectangles
|
2020-01-07 07:00:43 +13: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 20:16:18 +12:00
|
|
|
}
|
2020-01-06 00:27:24 +13:00
|
|
|
|
2018-06-10 20:16:18 +12: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-06 00:27:24 +13:00
|
|
|
|
2018-06-10 20:16:18 +12:00
|
|
|
// Circles
|
|
|
|
circle = symbol->vector->circles;
|
|
|
|
while (circle) {
|
|
|
|
if (circle->colour) {
|
|
|
|
// A 'white' circle
|
2016-06-20 01:14:30 +12:00
|
|
|
if ((symbol->output_options & CMYK_COLOUR) == 0) {
|
2018-06-10 20:16:18 +12:00
|
|
|
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_paper, green_paper, blue_paper);
|
2016-06-20 01:14:30 +12:00
|
|
|
} else {
|
2018-06-10 20:16:18 +12:00
|
|
|
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_paper, magenta_paper, yellow_paper, black_paper);
|
2016-02-21 00:29:19 +13:00
|
|
|
}
|
2018-06-10 20:16:18 +12:00
|
|
|
fprintf(feps, "%.2f %.2f %.2f TD\n", circle->x, (symbol->vector->height - circle->y), circle->diameter / 2.0);
|
|
|
|
if (circle->next) {
|
2016-08-29 03:38:02 +12: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-20 01:14:30 +12:00
|
|
|
} else {
|
2018-06-10 20:16:18 +12: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 22:59:09 +12:00
|
|
|
}
|
2018-06-10 20:16:18 +12:00
|
|
|
circle = circle->next;
|
2016-06-19 22:59:09 +12:00
|
|
|
}
|
2020-01-06 00:27:24 +13:00
|
|
|
|
2018-06-10 20:16:18 +12:00
|
|
|
// Text
|
|
|
|
string = symbol->vector->strings;
|
|
|
|
while (string) {
|
2016-02-21 00:29:19 +13:00
|
|
|
fprintf(feps, "matrix currentmatrix\n");
|
|
|
|
fprintf(feps, "/Helvetica findfont\n");
|
2018-06-10 20:16:18 +12: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-21 00:29:19 +13:00
|
|
|
fprintf(feps, "pop\n");
|
|
|
|
fprintf(feps, "-2 div 0 rmoveto\n");
|
2018-06-10 20:16:18 +12:00
|
|
|
fprintf(feps, " (%s) show\n", string->text);
|
2016-02-21 00:29:19 +13:00
|
|
|
fprintf(feps, "setmatrix\n");
|
2018-06-10 20:16:18 +12:00
|
|
|
string = string->next;
|
2016-02-21 00:29:19 +13:00
|
|
|
}
|
2020-01-06 00:27:24 +13:00
|
|
|
|
|
|
|
//fprintf(feps, "\nshowpage\n");
|
2016-02-21 00:29:19 +13:00
|
|
|
|
|
|
|
if (symbol->output_options & BARCODE_STDOUT) {
|
|
|
|
fflush(feps);
|
|
|
|
} else {
|
|
|
|
fclose(feps);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (locale)
|
|
|
|
setlocale(LC_ALL, locale);
|
|
|
|
|
|
|
|
return error_number;
|
2008-07-14 09:15:55 +12:00
|
|
|
}
|