1 /* ps.c - Post Script output */
2 
3 /*
4     libzint - the open source barcode library
5     Copyright (C) 2009-2017 Robin Stuart <rstuart114@gmail.com>
6 
7     Redistribution and use in source and binary forms, with or without
8     modification, are permitted provided that the following conditions
9     are met:
10 
11     1. Redistributions of source code must retain the above copyright
12        notice, this list of conditions and the following disclaimer.
13     2. Redistributions in binary form must reproduce the above copyright
14        notice, this list of conditions and the following disclaimer in the
15        documentation and/or other materials provided with the distribution.
16     3. Neither the name of the project nor the names of its contributors
17        may be used to endorse or promote products derived from this software
18        without specific prior written permission.
19 
20     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23     ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30     SUCH DAMAGE.
31  */
32 
33 #include <locale.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <math.h>
38 #include "common.h"
39 
40 #define SSET	"0123456789ABCDEF"
41 
ps_plot(struct zint_symbol * symbol)42 int ps_plot(struct zint_symbol *symbol) {
43     int i, block_width, latch, r, this_row;
44     float textpos, large_bar_height, preset_height, row_height, row_posn;
45     FILE *feps;
46     int fgred, fggrn, fgblu, bgred, bggrn, bgblu;
47     float red_ink, green_ink, blue_ink, red_paper, green_paper, blue_paper;
48     float cyan_ink, magenta_ink, yellow_ink, black_ink;
49     float cyan_paper, magenta_paper, yellow_paper, black_paper;
50     int error_number = 0;
51     int textoffset, xoffset, yoffset, textdone, main_width;
52     char textpart[10], addon[6];
53     int large_bar_count, comp_offset;
54     float addon_text_posn;
55     float scaler = symbol->scale;
56     float default_text_posn;
57     const char *locale = NULL;
58 #ifndef _MSC_VER
59     unsigned char local_text[ustrlen(symbol->text) + 1];
60 #else
61     unsigned char* local_text = (unsigned char*) malloc(ustrlen(symbol->text) + 1);
62 #endif
63 
64     row_height = 0;
65     textdone = 0;
66     main_width = symbol->width;
67     strcpy(addon, "");
68     comp_offset = 0;
69     addon_text_posn = 0.0;
70 
71     if (symbol->show_hrt != 0) {
72         /* Copy text from symbol */
73         ustrcpy(local_text, symbol->text);
74     } else {
75         /* No text needed */
76         switch (symbol->symbology) {
77             case BARCODE_EANX:
78             case BARCODE_EANX_CC:
79             case BARCODE_ISBNX:
80             case BARCODE_UPCA:
81             case BARCODE_UPCE:
82             case BARCODE_UPCA_CC:
83             case BARCODE_UPCE_CC:
84                 /* For these symbols use dummy text to ensure formatting is done
85                  * properly even if no text is required */
86                 for (i = 0; i < ustrlen(symbol->text); i++) {
87                     if (symbol->text[i] == '+') {
88                         local_text[i] = '+';
89                     } else {
90                         local_text[i] = ' ';
91                     }
92                     local_text[ustrlen(symbol->text)] = '\0';
93                 }
94                 break;
95             default:
96                 /* For everything else, just remove the text */
97                 local_text[0] = '\0';
98                 break;
99         }
100     }
101 
102     if (symbol->output_options & BARCODE_STDOUT) {
103         feps = stdout;
104     } else {
105         feps = fopen(symbol->outfile, "w");
106     }
107     if (feps == NULL) {
108         strcpy(symbol->errtxt, "645: Could not open output file");
109 #ifdef _MSC_VER
110         free(local_text);
111 #endif
112         return ZINT_ERROR_FILE_ACCESS;
113     }
114 
115     /* sort out colour options */
116     to_upper((unsigned char*) symbol->fgcolour);
117     to_upper((unsigned char*) symbol->bgcolour);
118 
119     if (strlen(symbol->fgcolour) != 6) {
120         strcpy(symbol->errtxt, "646: Malformed foreground colour target");
121         fclose(feps);
122 #ifdef _MSC_VER
123         free(local_text);
124 #endif
125         return ZINT_ERROR_INVALID_OPTION;
126     }
127     if (strlen(symbol->bgcolour) != 6) {
128         strcpy(symbol->errtxt, "647: Malformed background colour target");
129         fclose(feps);
130 #ifdef _MSC_VER
131         free(local_text);
132 #endif
133         return ZINT_ERROR_INVALID_OPTION;
134     }
135     error_number = is_sane(SSET, (unsigned char*) symbol->fgcolour, strlen(symbol->fgcolour));
136     if (error_number == ZINT_ERROR_INVALID_DATA) {
137         strcpy(symbol->errtxt, "648: Malformed foreground colour target");
138         fclose(feps);
139 #ifdef _MSC_VER
140         free(local_text);
141 #endif
142         return ZINT_ERROR_INVALID_OPTION;
143     }
144     error_number = is_sane(SSET, (unsigned char*) symbol->bgcolour, strlen(symbol->bgcolour));
145     if (error_number == ZINT_ERROR_INVALID_DATA) {
146         strcpy(symbol->errtxt, "649: Malformed background colour target");
147         fclose(feps);
148 #ifdef _MSC_VER
149         free(local_text);
150 #endif
151         return ZINT_ERROR_INVALID_OPTION;
152     }
153     locale = setlocale(LC_ALL, "C");
154 
155     fgred = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]);
156     fggrn = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]);
157     fgblu = (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]);
158     bgred = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]);
159     bggrn = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]);
160     bgblu = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]);
161     red_ink = fgred / 256.0;
162     green_ink = fggrn / 256.0;
163     blue_ink = fgblu / 256.0;
164     red_paper = bgred / 256.0;
165     green_paper = bggrn / 256.0;
166     blue_paper = bgblu / 256.0;
167 
168     /* Convert RGB to CMYK */
169     if (red_ink > green_ink) {
170         if (blue_ink > red_ink) {
171             black_ink = 1 - blue_ink;
172         } else {
173             black_ink = 1 - red_ink;
174         }
175     } else {
176         if (blue_ink > red_ink) {
177             black_ink = 1 - blue_ink;
178         } else {
179             black_ink = 1 - green_ink;
180         }
181     }
182     if (black_ink < 1.0) {
183         cyan_ink = (1 - red_ink - black_ink) / (1 - black_ink);
184         magenta_ink = (1 - green_ink - black_ink) / (1 - black_ink);
185         yellow_ink = (1 - blue_ink - black_ink) / (1 - black_ink);
186     } else {
187         cyan_ink = 0.0;
188         magenta_ink = 0.0;
189         yellow_ink = 0.0;
190     }
191 
192     if (red_paper > green_paper) {
193         if (blue_paper > red_paper) {
194             black_paper = 1 - blue_paper;
195         } else {
196             black_paper = 1 - red_paper;
197         }
198     } else {
199         if (blue_paper > red_paper) {
200             black_paper = 1 - blue_paper;
201         } else {
202             black_paper = 1 - green_paper;
203         }
204     }
205     if (black_paper < 1.0) {
206         cyan_paper = (1 - red_paper - black_paper) / (1 - black_paper);
207         magenta_paper = (1 - green_paper - black_paper) / (1 - black_paper);
208         yellow_paper = (1 - blue_paper - black_paper) / (1 - black_paper);
209     } else {
210         cyan_paper = 0.0;
211         magenta_paper = 0.0;
212         yellow_paper = 0.0;
213     }
214 
215     if (symbol->height == 0) {
216         symbol->height = 50;
217     }
218 
219     large_bar_count = 0;
220     preset_height = 0.0;
221     for (i = 0; i < symbol->rows; i++) {
222         preset_height += symbol->row_height[i];
223         if (symbol->row_height[i] == 0) {
224             large_bar_count++;
225         }
226     }
227     large_bar_height = (symbol->height - preset_height) / large_bar_count;
228 
229     if (large_bar_count == 0) {
230         symbol->height = preset_height;
231     }
232 
233     while (!(module_is_set(symbol, symbol->rows - 1, comp_offset))) {
234         comp_offset++;
235     }
236 
237     /* Certain symbols need whitespace otherwise characters get chopped off the sides */
238     if ((((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC))
239             || (symbol->symbology == BARCODE_ISBNX)) {
240         switch (ustrlen(local_text)) {
241             case 13: /* EAN 13 */
242             case 16:
243             case 19:
244                 if (symbol->whitespace_width == 0) {
245                     symbol->whitespace_width = 10;
246                 }
247                 main_width = 96 + comp_offset;
248                 break;
249             default:
250                 main_width = 68 + comp_offset;
251         }
252     }
253 
254     if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) {
255         if (symbol->whitespace_width == 0) {
256             symbol->whitespace_width = 10;
257             main_width = 96 + comp_offset;
258         }
259     }
260 
261     if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) {
262         if (symbol->whitespace_width == 0) {
263             symbol->whitespace_width = 10;
264             main_width = 51 + comp_offset;
265         }
266     }
267 
268     latch = 0;
269     r = 0;
270     /* Isolate add-on text */
271     if (is_extendable(symbol->symbology)) {
272         for (i = 0; i < ustrlen(local_text); i++) {
273             if (latch == 1) {
274                 addon[r] = local_text[i];
275                 r++;
276             }
277             if (local_text[i] == '+') {
278                 latch = 1;
279             }
280         }
281     }
282     addon[r] = '\0';
283 
284     if (ustrlen(local_text) != 0) {
285         textoffset = 9;
286     } else {
287         textoffset = 0;
288     }
289     xoffset = symbol->border_width + symbol->whitespace_width;
290     yoffset = symbol->border_width;
291 
292     /* Start writing the header */
293     fprintf(feps, "%%!PS-Adobe-3.0 EPSF-3.0\n");
294     fprintf(feps, "%%%%Creator: Zint %d.%d.%d\n", ZINT_VERSION_MAJOR, ZINT_VERSION_MINOR, ZINT_VERSION_RELEASE);
295     if ((ustrlen(local_text) != 0) && (symbol->show_hrt != 0)) {
296         fprintf(feps, "%%%%Title: %s\n", local_text);
297     } else {
298         fprintf(feps, "%%%%Title: Zint Generated Symbol\n");
299     }
300     fprintf(feps, "%%%%Pages: 0\n");
301     if (symbol->symbology != BARCODE_MAXICODE) {
302         fprintf(feps, "%%%%BoundingBox: 0 0 %d %d\n", (int) ceil((symbol->width + xoffset + xoffset) * scaler), (int) ceil((symbol->height + textoffset + yoffset + yoffset) * scaler));
303     } else {
304         fprintf(feps, "%%%%BoundingBox: 0 0 %d %d\n", (int) ceil((74.0F + xoffset + xoffset) * scaler), (int) ceil((72.0F + yoffset + yoffset) * scaler));
305     }
306     fprintf(feps, "%%%%EndComments\n");
307 
308     /* Definitions */
309     fprintf(feps, "/TL { setlinewidth moveto lineto stroke } bind def\n");
310     fprintf(feps, "/TC { moveto 0 360 arc 360 0 arcn fill } bind def\n");
311     fprintf(feps, "/TD { newpath 0 360 arc fill } bind def\n");
312     fprintf(feps, "/TH { 0 setlinewidth moveto lineto lineto lineto lineto lineto closepath fill } bind def\n");
313     fprintf(feps, "/TB { 2 copy } bind def\n");
314     fprintf(feps, "/TR { newpath 4 1 roll exch moveto 1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath fill } bind def\n");
315     fprintf(feps, "/TE { pop pop } bind def\n");
316 
317     fprintf(feps, "newpath\n");
318 
319     /* Now the actual representation */
320     if ((symbol->output_options & CMYK_COLOUR) == 0) {
321         fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
322         fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_paper, green_paper, blue_paper);
323     } else {
324         fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
325         fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_paper, magenta_paper, yellow_paper, black_paper);
326     }
327     fprintf(feps, "%.2f 0.00 TB 0.00 %.2f TR\n", (symbol->height + textoffset + yoffset + yoffset) * scaler, (symbol->width + xoffset + xoffset) * scaler);
328 
329     if (((symbol->output_options & BARCODE_BOX) != 0) || ((symbol->output_options & BARCODE_BIND) != 0)) {
330         default_text_posn = 0.5 * scaler;
331     } else {
332         default_text_posn = (symbol->border_width + 0.5) * scaler;
333     }
334 
335     if (symbol->symbology == BARCODE_MAXICODE) {
336         /* Maxicode uses hexagons */
337         float ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy, mx, my;
338 
339 
340         textoffset = 0.0;
341         if (((symbol->output_options & BARCODE_BOX) != 0) || ((symbol->output_options & BARCODE_BIND) != 0)) {
342             fprintf(feps, "TE\n");
343             if ((symbol->output_options & CMYK_COLOUR) == 0) {
344                 fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
345             } else {
346                 fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
347             }
348             fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, textoffset * scaler, 0.0, (74.0 + xoffset + xoffset) * scaler);
349             fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, (textoffset + 72.0 + symbol->border_width) * scaler, 0.0, (74.0 + xoffset + xoffset) * scaler);
350         }
351         if ((symbol->output_options & BARCODE_BOX) != 0) {
352             /* side bars */
353             fprintf(feps, "TE\n");
354             if ((symbol->output_options & CMYK_COLOUR) == 0) {
355                 fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
356             } else {
357                 fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
358             }
359             fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", (72.0 + (2 * symbol->border_width)) * scaler, textoffset * scaler, 0.0, symbol->border_width * scaler);
360             fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", (72.0 + (2 * symbol->border_width)) * scaler, textoffset * scaler, (74.0 + xoffset + xoffset - symbol->border_width) * scaler, symbol->border_width * scaler);
361         }
362 
363         fprintf(feps, "TE\n");
364         if ((symbol->output_options & CMYK_COLOUR) == 0) {
365             fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
366             fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
367         } else {
368             fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
369             fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
370         }
371         fprintf(feps, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f TC\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 10.85 * scaler, (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 8.97 * scaler, (44.73 + xoffset) * scaler, (35.60 + yoffset) * scaler);
372         fprintf(feps, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f TC\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 7.10 * scaler, (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 5.22 * scaler, (40.98 + xoffset) * scaler, (35.60 + yoffset) * scaler);
373         fprintf(feps, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f TC\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 3.31 * scaler, (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 1.43 * scaler, (37.19 + xoffset) * scaler, (35.60 + yoffset) * scaler);
374         for (r = 0; r < symbol->rows; r++) {
375             for (i = 0; i < symbol->width; i++) {
376                 if (module_is_set(symbol, r, i)) {
377                     /* Dump a hexagon */
378                     my = ((symbol->rows - r - 1)) * 2.135 + 1.43;
379                     ay = my + 1.0 + yoffset;
380                     by = my + 0.5 + yoffset;
381                     cy = my - 0.5 + yoffset;
382                     dy = my - 1.0 + yoffset;
383                     ey = my - 0.5 + yoffset;
384                     fy = my + 0.5 + yoffset;
385 
386                     mx = 2.46 * i + 1.23 + (r & 1 ? 1.23 : 0);
387 
388                     ax = mx + xoffset;
389                     bx = mx + 0.86 + xoffset;
390                     cx = mx + 0.86 + xoffset;
391                     dx = mx + xoffset;
392                     ex = mx - 0.86 + xoffset;
393                     fx = mx - 0.86 + xoffset;
394                     fprintf(feps, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f TH\n", ax * scaler, ay * scaler, bx * scaler, by * scaler, cx * scaler, cy * scaler, dx * scaler, dy * scaler, ex * scaler, ey * scaler, fx * scaler, fy * scaler);
395                 }
396             }
397         }
398     }
399 
400     if (symbol->symbology != BARCODE_MAXICODE) {
401         /* everything else uses rectangles (or squares) */
402         /* Works from the bottom of the symbol up */
403 
404         int addon_latch = 0;
405 
406         for (r = 0; r < symbol->rows; r++) {
407             this_row = symbol->rows - r - 1; /* invert r otherwise plots upside down */
408             if (symbol->row_height[this_row] == 0) {
409                 row_height = large_bar_height;
410             } else {
411                 row_height = symbol->row_height[this_row];
412             }
413             row_posn = 0;
414             for (i = 0; i < r; i++) {
415                 if (symbol->row_height[symbol->rows - i - 1] == 0) {
416                     row_posn += large_bar_height;
417                 } else {
418                     row_posn += symbol->row_height[symbol->rows - i - 1];
419                 }
420             }
421             row_posn += (textoffset + yoffset);
422 
423             if ((symbol->output_options & BARCODE_DOTTY_MODE) != 0) {
424                 if ((symbol->output_options & CMYK_COLOUR) == 0) {
425                     fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
426                 } else {
427                     fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
428                 }
429 
430                 /* Use dots instead of squares */
431                 for (i = 0; i < symbol->width; i++) {
432                     if (module_is_set(symbol, this_row, i)) {
433                         fprintf(feps, "%.2f %.2f %.2f TD\n", ((i + xoffset) * scaler) + (scaler / 2.0), (row_posn * scaler) + (scaler / 2.0), (symbol->dot_size / 2.0) * scaler);
434                     }
435                 }
436             } else {
437                 /* Normal mode, with rectangles */
438 
439                 fprintf(feps, "TE\n");
440                 if ((symbol->output_options & CMYK_COLOUR) == 0) {
441                     fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
442                 } else {
443                     fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
444                 }
445 
446                 fprintf(feps, "%.2f %.2f ", row_height * scaler, row_posn * scaler);
447                 i = 0;
448                 if (module_is_set(symbol, this_row, 0)) {
449                     latch = 1;
450                 } else {
451                     latch = 0;
452                 }
453 
454                 do {
455                     block_width = 0;
456                     do {
457                         block_width++;
458                     } while (module_is_set(symbol, this_row, i + block_width) == module_is_set(symbol, this_row, i));
459                     if ((addon_latch == 0) && (r == 0) && (i > main_width)) {
460                         fprintf(feps, "TE\n");
461                         if ((symbol->output_options & CMYK_COLOUR) == 0) {
462                             fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
463                         } else {
464                             fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
465                         }
466                         fprintf(feps, "%.2f %.2f ", (row_height - 5.0) * scaler, (row_posn - 5.0) * scaler);
467                         addon_text_posn = row_posn + row_height - 8.0;
468                         addon_latch = 1;
469                     }
470                     if (latch == 1) {
471                         /* a bar */
472                         fprintf(feps, "TB %.2f %.2f TR\n", (i + xoffset) * scaler, block_width * scaler);
473                         latch = 0;
474                     } else {
475                         /* a space */
476                         latch = 1;
477                     }
478                     i += block_width;
479 
480                 } while (i < symbol->width);
481             }
482         }
483     }
484     /* That's done the actual data area, everything else is human-friendly */
485 
486     xoffset += comp_offset;
487 
488     if ((((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC)) ||
489             (symbol->symbology == BARCODE_ISBNX)) {
490         /* guard bar extensions and text formatting for EAN8 and EAN13 */
491         switch (ustrlen(local_text)) {
492             case 8: /* EAN-8 */
493             case 11:
494             case 14:
495                 fprintf(feps, "TE\n");
496                 if ((symbol->output_options & CMYK_COLOUR) == 0) {
497                     fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
498                 } else {
499                     fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
500                 }
501                 fprintf(feps, "%.2f %.2f ", 5.0 * scaler, (4.0 + yoffset) * scaler);
502                 fprintf(feps, "TB %.2f %.2f TR\n", (0 + xoffset) * scaler, 1 * scaler);
503                 fprintf(feps, "TB %.2f %.2f TR\n", (2 + xoffset) * scaler, 1 * scaler);
504                 fprintf(feps, "TB %.2f %.2f TR\n", (32 + xoffset) * scaler, 1 * scaler);
505                 fprintf(feps, "TB %.2f %.2f TR\n", (34 + xoffset) * scaler, 1 * scaler);
506                 fprintf(feps, "TB %.2f %.2f TR\n", (64 + xoffset) * scaler, 1 * scaler);
507                 fprintf(feps, "TB %.2f %.2f TR\n", (66 + xoffset) * scaler, 1 * scaler);
508                 for (i = 0; i < 4; i++) {
509                     textpart[i] = local_text[i];
510                 }
511                 textpart[4] = '\0';
512                 fprintf(feps, "TE\n");
513                 if ((symbol->output_options & CMYK_COLOUR) == 0) {
514                     fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
515                 } else {
516                     fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
517                 }
518                 fprintf(feps, "matrix currentmatrix\n");
519                 fprintf(feps, "/Helvetica findfont\n");
520                 fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
521                 textpos = 17;
522                 fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
523                 fprintf(feps, " (%s) stringwidth\n", textpart);
524                 fprintf(feps, "pop\n");
525                 fprintf(feps, "-2 div 0 rmoveto\n");
526                 fprintf(feps, " (%s) show\n", textpart);
527                 fprintf(feps, "setmatrix\n");
528                 for (i = 0; i < 4; i++) {
529                     textpart[i] = local_text[i + 4];
530                 }
531                 textpart[4] = '\0';
532                 fprintf(feps, "matrix currentmatrix\n");
533                 fprintf(feps, "/Helvetica findfont\n");
534                 fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
535                 textpos = 50;
536                 fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
537                 fprintf(feps, " (%s) stringwidth\n", textpart);
538                 fprintf(feps, "pop\n");
539                 fprintf(feps, "-2 div 0 rmoveto\n");
540                 fprintf(feps, " (%s) show\n", textpart);
541                 fprintf(feps, "setmatrix\n");
542                 textdone = 1;
543                 switch (strlen(addon)) {
544                     case 2:
545                         fprintf(feps, "matrix currentmatrix\n");
546                         fprintf(feps, "/Helvetica findfont\n");
547                         fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
548                         textpos = xoffset + 86;
549                         fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
550                         fprintf(feps, " (%s) stringwidth\n", addon);
551                         fprintf(feps, "pop\n");
552                         fprintf(feps, "-2 div 0 rmoveto\n");
553                         fprintf(feps, " (%s) show\n", addon);
554                         fprintf(feps, "setmatrix\n");
555                         break;
556                     case 5:
557                         fprintf(feps, "matrix currentmatrix\n");
558                         fprintf(feps, "/Helvetica findfont\n");
559                         fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
560                         textpos = xoffset + 100;
561                         fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
562                         fprintf(feps, " (%s) stringwidth\n", addon);
563                         fprintf(feps, "pop\n");
564                         fprintf(feps, "-2 div 0 rmoveto\n");
565                         fprintf(feps, " (%s) show\n", addon);
566                         fprintf(feps, "setmatrix\n");
567                         break;
568                 }
569 
570                 break;
571             case 13: /* EAN 13 */
572             case 16:
573             case 19:
574                 fprintf(feps, "TE\n");
575                 if ((symbol->output_options & CMYK_COLOUR) == 0) {
576                     fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
577                 } else {
578                     fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
579                 }
580                 fprintf(feps, "%.2f %.2f ", 5.0 * scaler, (4.0 + yoffset) * scaler);
581                 fprintf(feps, "TB %.2f %.2f TR\n", (0 + xoffset) * scaler, 1 * scaler);
582                 fprintf(feps, "TB %.2f %.2f TR\n", (2 + xoffset) * scaler, 1 * scaler);
583                 fprintf(feps, "TB %.2f %.2f TR\n", (46 + xoffset) * scaler, 1 * scaler);
584                 fprintf(feps, "TB %.2f %.2f TR\n", (48 + xoffset) * scaler, 1 * scaler);
585                 fprintf(feps, "TB %.2f %.2f TR\n", (92 + xoffset) * scaler, 1 * scaler);
586                 fprintf(feps, "TB %.2f %.2f TR\n", (94 + xoffset) * scaler, 1 * scaler);
587                 textpart[0] = local_text[0];
588                 textpart[1] = '\0';
589                 fprintf(feps, "TE\n");
590                 if ((symbol->output_options & CMYK_COLOUR) == 0) {
591                     fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
592                 } else {
593                     fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
594                 }
595                 fprintf(feps, "matrix currentmatrix\n");
596                 fprintf(feps, "/Helvetica findfont\n");
597                 fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
598                 textpos = -7;
599                 fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
600                 fprintf(feps, " (%s) stringwidth\n", textpart);
601                 fprintf(feps, "pop\n");
602                 fprintf(feps, "-2 div 0 rmoveto\n");
603                 fprintf(feps, " (%s) show\n", textpart);
604                 fprintf(feps, "setmatrix\n");
605                 for (i = 0; i < 6; i++) {
606                     textpart[i] = local_text[i + 1];
607                 }
608                 textpart[6] = '\0';
609                 fprintf(feps, "matrix currentmatrix\n");
610                 fprintf(feps, "/Helvetica findfont\n");
611                 fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
612                 textpos = 24;
613                 fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
614                 fprintf(feps, " (%s) stringwidth\n", textpart);
615                 fprintf(feps, "pop\n");
616                 fprintf(feps, "-2 div 0 rmoveto\n");
617                 fprintf(feps, " (%s) show\n", textpart);
618                 fprintf(feps, "setmatrix\n");
619                 for (i = 0; i < 6; i++) {
620                     textpart[i] = local_text[i + 7];
621                 }
622                 textpart[6] = '\0';
623                 fprintf(feps, "matrix currentmatrix\n");
624                 fprintf(feps, "/Helvetica findfont\n");
625                 fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
626                 textpos = 71;
627                 fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
628                 fprintf(feps, " (%s) stringwidth\n", textpart);
629                 fprintf(feps, "pop\n");
630                 fprintf(feps, "-2 div 0 rmoveto\n");
631                 fprintf(feps, " (%s) show\n", textpart);
632                 fprintf(feps, "setmatrix\n");
633                 textdone = 1;
634                 switch (strlen(addon)) {
635                     case 2:
636                         fprintf(feps, "matrix currentmatrix\n");
637                         fprintf(feps, "/Helvetica findfont\n");
638                         fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
639                         textpos = xoffset + 114;
640                         fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
641                         fprintf(feps, " (%s) stringwidth\n", addon);
642                         fprintf(feps, "pop\n");
643                         fprintf(feps, "-2 div 0 rmoveto\n");
644                         fprintf(feps, " (%s) show\n", addon);
645                         fprintf(feps, "setmatrix\n");
646                         break;
647                     case 5:
648                         fprintf(feps, "matrix currentmatrix\n");
649                         fprintf(feps, "/Helvetica findfont\n");
650                         fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
651                         textpos = xoffset + 128;
652                         fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
653                         fprintf(feps, " (%s) stringwidth\n", addon);
654                         fprintf(feps, "pop\n");
655                         fprintf(feps, "-2 div 0 rmoveto\n");
656                         fprintf(feps, " (%s) show\n", addon);
657                         fprintf(feps, "setmatrix\n");
658                         break;
659                 }
660                 break;
661 
662         }
663     }
664 
665     if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) {
666         /* guard bar extensions and text formatting for UPCA */
667         fprintf(feps, "TE\n");
668         if ((symbol->output_options & CMYK_COLOUR) == 0) {
669             fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
670         } else {
671             fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
672         }
673         fprintf(feps, "%.2f %.2f ", 5.0 * scaler, (4.0 + yoffset) * scaler);
674         latch = 1;
675 
676         i = 0 + comp_offset;
677         do {
678             block_width = 0;
679             do {
680                 block_width++;
681             } while (module_is_set(symbol, symbol->rows - 1, i + block_width) == module_is_set(symbol, symbol->rows - 1, i));
682             if (latch == 1) {
683                 /* a bar */
684                 fprintf(feps, "TB %.2f %.2f TR\n", (i + xoffset - comp_offset) * scaler, block_width * scaler);
685                 latch = 0;
686             } else {
687                 /* a space */
688                 latch = 1;
689             }
690             i += block_width;
691         } while (i < 11 + comp_offset);
692         fprintf(feps, "TB %.2f %.2f TR\n", (46 + xoffset) * scaler, 1 * scaler);
693         fprintf(feps, "TB %.2f %.2f TR\n", (48 + xoffset) * scaler, 1 * scaler);
694         latch = 1;
695         i = 85 + comp_offset;
696         do {
697             block_width = 0;
698             do {
699                 block_width++;
700             } while (module_is_set(symbol, symbol->rows - 1, i + block_width) == module_is_set(symbol, symbol->rows - 1, i));
701             if (latch == 1) {
702                 /* a bar */
703                 fprintf(feps, "TB %.2f %.2f TR\n", (i + xoffset - comp_offset) * scaler, block_width * scaler);
704                 latch = 0;
705             } else {
706                 /* a space */
707                 latch = 1;
708             }
709             i += block_width;
710         } while (i < 96 + comp_offset);
711         textpart[0] = local_text[0];
712         textpart[1] = '\0';
713         fprintf(feps, "TE\n");
714         if ((symbol->output_options & CMYK_COLOUR) == 0) {
715             fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
716         } else {
717             fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
718         }
719         fprintf(feps, "matrix currentmatrix\n");
720         fprintf(feps, "/Helvetica findfont\n");
721         fprintf(feps, "%.2f scalefont setfont\n", 8.0 * scaler);
722         textpos = -5;
723         fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
724         fprintf(feps, " (%s) stringwidth\n", textpart);
725         fprintf(feps, "pop\n");
726         fprintf(feps, "-2 div 0 rmoveto\n");
727         fprintf(feps, " (%s) show\n", textpart);
728         fprintf(feps, "setmatrix\n");
729         for (i = 0; i < 5; i++) {
730             textpart[i] = local_text[i + 1];
731         }
732         textpart[5] = '\0';
733         fprintf(feps, "matrix currentmatrix\n");
734         fprintf(feps, "/Helvetica findfont\n");
735         fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
736         textpos = 27;
737         fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
738         fprintf(feps, " (%s) stringwidth\n", textpart);
739         fprintf(feps, "pop\n");
740         fprintf(feps, "-2 div 0 rmoveto\n");
741         fprintf(feps, " (%s) show\n", textpart);
742         fprintf(feps, "setmatrix\n");
743         for (i = 0; i < 5; i++) {
744             textpart[i] = local_text[i + 6];
745         }
746         textpart[6] = '\0';
747         fprintf(feps, "matrix currentmatrix\n");
748         fprintf(feps, "/Helvetica findfont\n");
749         fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
750         textpos = 68;
751         fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
752         fprintf(feps, " (%s) stringwidth\n", textpart);
753         fprintf(feps, "pop\n");
754         fprintf(feps, "-2 div 0 rmoveto\n");
755         fprintf(feps, " (%s) show\n", textpart);
756         fprintf(feps, "setmatrix\n");
757         textpart[0] = local_text[11];
758         textpart[1] = '\0';
759         fprintf(feps, "matrix currentmatrix\n");
760         fprintf(feps, "/Helvetica findfont\n");
761         fprintf(feps, "%.2f scalefont setfont\n", 8.0 * scaler);
762         textpos = 100;
763         fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
764         fprintf(feps, " (%s) stringwidth\n", textpart);
765         fprintf(feps, "pop\n");
766         fprintf(feps, "-2 div 0 rmoveto\n");
767         fprintf(feps, " (%s) show\n", textpart);
768         fprintf(feps, "setmatrix\n");
769         textdone = 1;
770         switch (strlen(addon)) {
771             case 2:
772                 fprintf(feps, "matrix currentmatrix\n");
773                 fprintf(feps, "/Helvetica findfont\n");
774                 fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
775                 textpos = xoffset + 116;
776                 fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
777                 fprintf(feps, " (%s) stringwidth\n", addon);
778                 fprintf(feps, "pop\n");
779                 fprintf(feps, "-2 div 0 rmoveto\n");
780                 fprintf(feps, " (%s) show\n", addon);
781                 fprintf(feps, "setmatrix\n");
782                 break;
783             case 5:
784                 fprintf(feps, "matrix currentmatrix\n");
785                 fprintf(feps, "/Helvetica findfont\n");
786                 fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
787                 textpos = xoffset + 130;
788                 fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
789                 fprintf(feps, " (%s) stringwidth\n", addon);
790                 fprintf(feps, "pop\n");
791                 fprintf(feps, "-2 div 0 rmoveto\n");
792                 fprintf(feps, " (%s) show\n", addon);
793                 fprintf(feps, "setmatrix\n");
794                 break;
795         }
796 
797     }
798 
799     if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) {
800         /* guard bar extensions and text formatting for UPCE */
801         fprintf(feps, "TE\n");
802         if ((symbol->output_options & CMYK_COLOUR) == 0) {
803             fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
804         } else {
805             fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
806         }
807         fprintf(feps, "%.2f %.2f ", 5.0 * scaler, (4.0 + yoffset) * scaler);
808         fprintf(feps, "TB %.2f %.2f TR\n", (0 + xoffset) * scaler, 1 * scaler);
809         fprintf(feps, "TB %.2f %.2f TR\n", (2 + xoffset) * scaler, 1 * scaler);
810         fprintf(feps, "TB %.2f %.2f TR\n", (46 + xoffset) * scaler, 1 * scaler);
811         fprintf(feps, "TB %.2f %.2f TR\n", (48 + xoffset) * scaler, 1 * scaler);
812         fprintf(feps, "TB %.2f %.2f TR\n", (50 + xoffset) * scaler, 1 * scaler);
813         textpart[0] = local_text[0];
814         textpart[1] = '\0';
815         fprintf(feps, "TE\n");
816         fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
817         fprintf(feps, "matrix currentmatrix\n");
818         fprintf(feps, "/Helvetica findfont\n");
819         fprintf(feps, "%.2f scalefont setfont\n", 8.0 * scaler);
820         textpos = -5;
821         fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
822         fprintf(feps, " (%s) stringwidth\n", textpart);
823         fprintf(feps, "pop\n");
824         fprintf(feps, "-2 div 0 rmoveto\n");
825         fprintf(feps, " (%s) show\n", textpart);
826         fprintf(feps, "setmatrix\n");
827         for (i = 0; i < 6; i++) {
828             textpart[i] = local_text[i + 1];
829         }
830         textpart[6] = '\0';
831         fprintf(feps, "matrix currentmatrix\n");
832         fprintf(feps, "/Helvetica findfont\n");
833         fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
834         textpos = 24;
835         fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
836         fprintf(feps, " (%s) stringwidth\n", textpart);
837         fprintf(feps, "pop\n");
838         fprintf(feps, "-2 div 0 rmoveto\n");
839         fprintf(feps, " (%s) show\n", textpart);
840         fprintf(feps, "setmatrix\n");
841         textpart[0] = local_text[7];
842         textpart[1] = '\0';
843         fprintf(feps, "matrix currentmatrix\n");
844         fprintf(feps, "/Helvetica findfont\n");
845         fprintf(feps, "%.2f scalefont setfont\n", 8.0 * scaler);
846         textpos = 55;
847         fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
848         fprintf(feps, " (%s) stringwidth\n", textpart);
849         fprintf(feps, "pop\n");
850         fprintf(feps, "-2 div 0 rmoveto\n");
851         fprintf(feps, " (%s) show\n", textpart);
852         fprintf(feps, "setmatrix\n");
853         textdone = 1;
854         switch (strlen(addon)) {
855             case 2:
856                 fprintf(feps, "matrix currentmatrix\n");
857                 fprintf(feps, "/Helvetica findfont\n");
858                 fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
859                 textpos = xoffset + 70;
860                 fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
861                 fprintf(feps, " (%s) stringwidth\n", addon);
862                 fprintf(feps, "pop\n");
863                 fprintf(feps, "-2 div 0 rmoveto\n");
864                 fprintf(feps, " (%s) show\n", addon);
865                 fprintf(feps, "setmatrix\n");
866                 break;
867             case 5:
868                 fprintf(feps, "matrix currentmatrix\n");
869                 fprintf(feps, "/Helvetica findfont\n");
870                 fprintf(feps, "%.2f scalefont setfont\n", 11.0 * scaler);
871                 textpos = xoffset + 84;
872                 fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
873                 fprintf(feps, " (%s) stringwidth\n", addon);
874                 fprintf(feps, "pop\n");
875                 fprintf(feps, "-2 div 0 rmoveto\n");
876                 fprintf(feps, " (%s) show\n", addon);
877                 fprintf(feps, "setmatrix\n");
878                 break;
879         }
880 
881     }
882 
883     xoffset -= comp_offset;
884 
885     switch (symbol->symbology) {
886         case BARCODE_MAXICODE:
887             /* Do nothing! (It's already been done) */
888             break;
889         default:
890             if (symbol->output_options & BARCODE_BIND) {
891                 if ((symbol->rows > 1) && (is_stackable(symbol->symbology) == 1)) {
892                     /* row binding */
893                     fprintf(feps, "TE\n");
894                     if ((symbol->output_options & CMYK_COLOUR) == 0) {
895                         fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
896                     } else {
897                         fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
898                     }
899                     if (symbol->symbology != BARCODE_CODABLOCKF) {
900                         for (r = 1; r < symbol->rows; r++) {
901                             fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", 2.0 * scaler, ((r * row_height) + textoffset + yoffset - 1) * scaler, xoffset * scaler, symbol->width * scaler);
902                         }
903                     } else {
904                         for (r = 1; r < symbol->rows; r++) {
905                             fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", 2.0 * scaler, ((r * row_height) + textoffset + yoffset - 1) * scaler, (xoffset + 11) * scaler, (symbol->width - 25) * scaler);
906                         }
907                     }
908                 }
909             }
910             if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) {
911                 fprintf(feps, "TE\n");
912                 if ((symbol->output_options & CMYK_COLOUR) == 0) {
913                     fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
914                 } else {
915                     fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
916                 }
917                 if (symbol->symbology != BARCODE_CODABLOCKF) {
918                     fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, textoffset * scaler, 0.0, (symbol->width + xoffset + xoffset) * scaler);
919                     fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, (textoffset + symbol->height + symbol->border_width) * scaler, 0.0, (symbol->width + xoffset + xoffset) * scaler);
920                 } else {
921                     fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, textoffset * scaler, xoffset * scaler, symbol->width * scaler);
922                     fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, (textoffset + symbol->height + symbol->border_width) * scaler, xoffset * scaler, symbol->width * scaler);
923                 }
924             }
925             if (symbol->output_options & BARCODE_BOX) {
926                 /* side bars */
927                 fprintf(feps, "TE\n");
928                 if ((symbol->output_options & CMYK_COLOUR) == 0) {
929                     fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
930                 } else {
931                     fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
932                 }
933                 fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", (symbol->height + (2 * symbol->border_width)) * scaler, textoffset * scaler, 0.0, symbol->border_width * scaler);
934                 fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", (symbol->height + (2 * symbol->border_width)) * scaler, textoffset * scaler, (symbol->width + xoffset + xoffset - symbol->border_width) * scaler, symbol->border_width * scaler);
935             }
936             break;
937     }
938 
939     /* Put the human readable text at the bottom */
940     if ((textdone == 0) && (ustrlen(local_text))) {
941         fprintf(feps, "TE\n");
942         if ((symbol->output_options & CMYK_COLOUR) == 0) {
943             fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
944         } else {
945             fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
946         }
947         fprintf(feps, "matrix currentmatrix\n");
948         fprintf(feps, "/Helvetica findfont\n");
949         fprintf(feps, "%.2f scalefont setfont\n", 8.0 * scaler);
950         textpos = symbol->width / 2.0;
951         fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
952         fprintf(feps, " (%s) stringwidth\n", local_text);
953         fprintf(feps, "pop\n");
954         fprintf(feps, "-2 div 0 rmoveto\n");
955         fprintf(feps, " (%s) show\n", local_text);
956         fprintf(feps, "setmatrix\n");
957     }
958     fprintf(feps, "\nshowpage\n");
959 
960     if (symbol->output_options & BARCODE_STDOUT) {
961         fflush(feps);
962     } else {
963         fclose(feps);
964     }
965 
966     if (locale)
967         setlocale(LC_ALL, locale);
968 
969 #ifdef _MSC_VER
970     free(local_text);
971 #endif
972 
973     return error_number;
974 }
975