1 /*
2 Copyright (c) 1991 - 1994 Heinz W. Werntges. All rights reserved.
3 Parts Copyright (c) 1999 Martin Kroeker All rights reserved.
4
5 Distributed by Free Software Foundation, Inc.
6
7 This file is part of HP2xx.
8
9 HP2xx is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
11 to anyone for the consequences of using it or for whether it serves any
12 particular purpose or works at all, unless he says so in writing. Refer
13 to the GNU General Public License, Version 2 or later, for full details.
14
15 Everyone is granted permission to copy, modify and redistribute
16 HP2xx, but only under the conditions described in the GNU General Public
17 License. A copy of this license is supposed to have been
18 given to you along with HP2xx so you can know your rights and
19 responsibilities. It should be in a file named COPYING. Among other
20 things, the copyright notice and this notice must be preserved on all
21 copies.
22
23 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
24 */
25
26 /** to_escp2.c: Epson Esc/P2 converter part of project "hp2xx"
27 ** derived from to_pcl.c
28 **
29 ** 00/02/27 MK initial version based on to_pcl.c
30 **/
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include "bresnham.h"
36 #include "hp2xx.h"
37 #include "pendef.h"
38
39 #define ESCP2_FIRST 1 /* Bit mask! */
40 #define ESCP2_LAST 2 /* Bit mask! */
41
42
43 /**
44 ** Used for compression ON/off switch:
45 **/
46 /*static int Deskjet_specials = TRUE;*/
47
48
49 /**
50 ** Buffers for color treatment
51 **/
52 static Byte *p_K, *p_C, *p_M, *p_Y; /* Buffer ptrs (CMYK bits) */
53
54
55
56 /**
57 ** Data & functions for (RLE) compression:
58 **
59 ** Note: Usually, the buffer p_B receives less data than the
60 ** original (i.e., < nb). However, "temporary" increases
61 ** are possible. To allow for them, we allocate a few extra bytes.
62 ** If the buffer eventually really grows, we won't use compression!
63 ** "n_B" keeps track of the amount of extra buffer space left.
64 **/
65 #define B_EXTRASPACE 16
66 static Byte *p_B; /* Buffer for compression */
67 static int n_B; /* Counter for extra space */
68
69
70
71
RLE_n_repeats(Byte * p1,int nb)72 static int RLE_n_repeats(Byte * p1, int nb)
73 /**
74 ** There are "nb" bytes in buffer "p1"
75 ** Return number of identical bytes in a sequence (0, 2 ... nb)
76 **/
77 {
78 int i;
79 Byte *p2;
80
81 p2 = p1 + 1;
82 if (nb < 2 || *p2 != *p1)
83 return 0;
84 for (i = 1; i < nb && *p1 == *p2; p1++, p2++)
85 i++;
86 return i;
87 }
88
89
90
RLE_n_irregs(Byte * p1,int nb)91 static int RLE_n_irregs(Byte * p1, int nb)
92 /**
93 ** There are "nb" bytes in buffer "p1"
94 ** Return number of irregular (non-identical) bytes
95 ** in a sequence (0, 1, 2 ... nb)
96 **/
97 {
98 int i;
99 Byte *p2;
100
101 if (nb < 2)
102 return nb; /* 0 or 1 */
103 p2 = p1 + 1;
104 for (i = 1; i < nb && *p1 != *p2; p1++, p2++)
105 i++;
106 return (i == nb) ? nb : i - 1;
107 }
108
109
110
RLE_compress(Byte * src,Byte * dst,int nb)111 static int RLE_compress(Byte * src, Byte * dst, int nb)
112 {
113 /**
114 ** Either there is a block of repetitions or non-repeating bytes
115 ** at the buffer start. If repetitions, compress them. If not,
116 ** buffer them and compress next block of repetitions.
117 **/
118 int i, l, count = 0;
119
120 l = RLE_n_repeats(src, nb); /* l == 0 or l >= 2 */
121 while (l > 128) {
122 *dst++ = (-127); /* 128 repetitions */
123 *dst++ = *src;
124 count += 2;
125 l -= 128;
126 nb -= 128;
127 src += 128;
128 n_B += 126; /* 128 bytes coded as 2 */
129
130 }
131 if (l > 0) {
132 *dst++ = (Byte) (1 - l); /* l repetitions */
133 *dst++ = *src;
134 count += 2;
135 src += l;
136 nb -= l;
137 n_B += (l - 2); /* l bytes coded as 2 */
138 }
139
140 if (nb < 0)
141 return -1; /* should never happen */
142 if (nb == 0)
143 return count; /* "count" bytes buffered */
144
145
146 /* Irregular sequence */
147
148 l = RLE_n_irregs(src, nb); /* l == 0 or l >= 2 */
149 while (l > 128) {
150 n_B -= 1;
151 if (n_B < 0)
152 return -1; /* Buffer overflow! */
153
154 *dst++ = 127; /* 128 repetitions */
155 for (i = 0; i < 128; i++)
156 *dst++ = *src++;
157 count += 129;
158 l -= 128;
159 nb -= 128;
160
161 }
162 if (l > 0) {
163 n_B -= 1;
164 if (n_B < 0)
165 return -1; /* Buffer overflow! */
166
167 *dst++ = (Byte) (l - 1); /* l repetitions */
168 for (i = 0; i < l; i++)
169 *dst++ = *src++;
170 count += (l + 1);
171 nb -= l;
172 }
173
174 if (nb < 0)
175 return -1; /* should never happen */
176
177 if (nb == 0) { /* At end-of-buffer: evaluate */
178 if (n_B > B_EXTRASPACE) /* Regular exit: Return */
179 return count; /* number of compressed bytes */
180 else
181 return -1; /* Nothing gained ! */
182 }
183 i = RLE_compress(src, dst, nb); /* Recursion for rest */
184 return (i == -1) ? -1 : i + count;
185 }
186
187
188
189 /**
190 ** ESCP2 data compression method #2 (RLE)
191 **
192 ** Compress data in buf; leave compressed data there.
193 ** Return number of valid bytes in buf of OK.
194 ** Return -1 if no compression done.
195 **/
196
compress_buf_RLE(Byte * buf,int nb)197 static int compress_buf_RLE(Byte * buf, int nb)
198 {
199
200 if (p_B == NULL) /* No buffer for compression! */
201 return -1;
202
203 n_B = B_EXTRASPACE; /* Init. extra space counter */
204 return RLE_compress(buf, p_B, nb); /* Recursive function! */
205 }
206
207
208
209
Buf_to_ESCP2(Byte * buf,int nb,int mode,FILE * fd)210 static void Buf_to_ESCP2(Byte * buf, int nb, int mode, FILE * fd)
211 /**
212 ** Output the raw bit stream
213 **/
214 {
215 int ncb; /* Number of compressed bytes */
216 Byte *p; /* Buffer pointer */
217
218
219 ncb = compress_buf_RLE(buf, nb);
220 if (ncb == -1) {
221 ncb = nb;
222 p = buf; /* Use original buffer & length */
223 fprintf(stderr, "compression failed\n");
224 } else {
225 p = p_B; /* Use compression buffer */
226 /*fprintf(stderr,"sending compressed data (%d bytes from %d bytes)\n",ncb,nb);*/
227 }
228 (void) fwrite(p, (size_t) ncb, 1, fd);
229 }
230
231
232
233
KCMY_Buf_to_ESCP2(int nb,int is_photo,int width,FILE * fd)234 static void KCMY_Buf_to_ESCP2(int nb, int is_photo, int width, FILE * fd)
235 /*KCMY_Buf_to_ESCP2 (int nb, int is_KCMY, int width, FILE *fd)*/
236 {
237
238 /* if (is_KCMY)
239 {*/
240 if (p_K[0] == 0 && memcmp(p_K, p_K + 1, (size_t) nb) == 0) {
241 /*fprintf(stderr,"skipping empty line of black\n");*/
242 } else {
243 putc('\r', fd); /* move print head to start of line */
244 if (is_photo)
245 (void) fwrite("\033(r2\000\000", 6, 1, fd);
246 else
247 (void) fwrite("\033r\000", 3, 1, fd); /* set color black */
248 (void) fwrite("\033.\001\005\005\001", 6, 1, fd); /* announce RLE data */
249 putc(width & 255, fd); /*width of raster line in pixels */
250 putc(width >> 8, fd);
251 Buf_to_ESCP2(p_K, nb, 0, fd); /* compress and send black pixels */
252 }
253 /*}*/
254
255 if (p_M[0] == 0 && memcmp(p_M, p_M + 1, (size_t) nb) == 0) {
256 /*fprintf(stderr,"skipping empty line of magenta\n");*/
257 } else {
258 putc('\r', fd); /* move print head to start of line */
259 if (is_photo)
260 (void) fwrite("\033(r2\000\001", 6, 1, fd);
261 else
262 fprintf(fd, "\033r\001"); /* set color magenta */
263 (void) fwrite("\033.\001\005\005\001", 6, 1, fd); /* announce RLE data */
264 putc(width & 255, fd); /*width of raster line in pixels */
265 putc(width >> 8, fd);
266 Buf_to_ESCP2(p_M, nb, 0, fd);
267 }
268 if (p_C[0] == 0
269 && memcmp(p_C, p_C + 1, (size_t) (3 * nb - 1)) == 0) {
270 /*fprintf(stderr,"skipping empty line of cyan\n");*/
271 } else {
272
273 putc('\r', fd);
274
275 if (is_photo)
276 (void) fwrite("\033(r2\000\002", 6, 1, fd);
277 else
278 fprintf(fd, "\033r\002"); /* set color cyan */
279 (void) fwrite("\033.\001\005\005\001", 6, 1, fd);
280 putc(width & 255, fd); /*width of raster line in pixels */
281 putc(width >> 8, fd);
282 Buf_to_ESCP2(p_C, nb, 0, fd);
283 }
284 if (p_Y[0] == 0
285 && memcmp(p_Y, p_Y + 1, (size_t) (3 * nb - 1)) == 0) {
286 /*fprintf(stderr,"skipping empty line of yellow\n");*/
287 } else {
288
289 putc('\r', fd);
290
291 if (is_photo)
292 (void) fwrite("\033(r2\000\004", 6, 1, fd);
293 else
294 fprintf(fd, "\033r\004"); /* set color yellow */
295 (void) fwrite("\033.\001\005\005\001", 6, 1, fd);
296 putc(width & 255, fd); /*width of raster line in pixels */
297 putc(width >> 8, fd);
298 Buf_to_ESCP2(p_Y, nb, 0, fd);
299 /* putc('\r',fd);*/
300 }
301 }
302
303
304
305 #if 0
306 static void KCMY_to_K(int nb)
307 /**
308 ** Color -> B/W conversion:
309 ** Any set bit will show up black
310 **/
311 {
312 int i;
313 Byte *pK = p_K, *pC = p_C, *pM = p_M, *pY = p_Y;
314
315 for (i = 0; i < nb; i++)
316 *pK++ |= ((*pC++ | *pM++) | *pY++);
317 }
318
319
320
321
322 static void K_to_CMY(int nb)
323 /**
324 ** CMYK-to-CMY conversion:
325 ** Any set bit in the "black" layer sets all C,M,Y bits to emulate "black"
326 **/
327 {
328 int i;
329 Byte *pK = p_K, *pC = p_C, *pM = p_M, *pY = p_Y;
330
331 for (i = 0; i < nb; i++, pK++) {
332 *pC++ |= *pK;
333 *pM++ |= *pK;
334 *pY++ |= *pK;
335 }
336 }
337
338 #endif
339
340
init_printer(const OUT_PAR * po,FILE * fd)341 static void init_printer(const OUT_PAR * po, FILE * fd)
342 {
343 int size;
344
345
346 size = 26; /* default to A4 paper */
347
348 if ((po->width >= po->height
349 && (po->width > 297. || po->height > 210.))
350 || (po->width < po->height
351 && (po->height > 297. || po->width > 210.)))
352 size = 27; /* A3 format */
353
354 if ((po->width >= po->height
355 && (po->width > 420. || po->height > 297.))
356 || (po->width < po->height
357 && (po->height > 420. || po->width > 297.)))
358 size = 28; /* A2 format */
359
360 if ((po->width >= po->height
361 && (po->width > 584. || po->height > 420.))
362 || (po->width < po->height
363 && (po->height > 584. || po->width > 420.)))
364 size = 29; /* A1 format */
365
366
367 if ((po->width >= po->height
368 && (po->width > 820. || po->height > 584.))
369 || (po->width < po->height
370 && (po->height > 820. || po->width > 584.)))
371 size = 30; /* A0 format :-) */
372
373 /* \033@ reset printer */
374 /* \033(G select graphics mode */
375 /* \033(i00011n set microweave on/off (off) */
376 /* \033(U10 set unidirectional off */
377 fputs("\033@", fd);
378 (void) fwrite("\033(G\001\000\001", 6, 1, fd); /* Enter graphics mode */
379 /* (void)fwrite("\033(U\001\000\005", 5, 1, fd);*//*set unidirectional off */
380 (void) fwrite("\033(U\001\000", 5, 1, fd); /* set resolution, unidirectional off */
381 size = 3600 / po->dpi_y;
382 putc(size, fd);
383 (void) fwrite("\033(i\001\000\001", 6, 1, fd); /* Microweave mode on */
384 (void) fwrite("\033(C\002\000", 5, 1, fd); /* Page length */
385 size = po->dpi_y * po->height;
386 putc(size & 255, fd);
387 putc(size >> 8, fd);
388
389 (void) fwrite("\033(c\004\000", 5, 1, fd); /* Top/bottom margins */
390 size = po->dpi_y * (po->height - 10) * .003937;
391 putc(size & 255, fd);
392 putc(size >> 8, fd);
393 size = po->dpi_y * (po->height - 10) * .003937;
394 putc(size & 255, fd);
395 putc(size >> 8, fd);
396
397 (void) fwrite("\033(V\002\000", 5, 1, fd); /* Absolute vertical position */
398 size = po->dpi_y * (po->height - 10) * .003937;
399 size = 10;
400 putc(size & 255, fd);
401 putc(size >> 8, fd);
402
403
404
405 }
406
407
408
409
410
end_graphmode(FILE * fd)411 static void end_graphmode(FILE * fd)
412 {
413 /**
414 ** End Raster Graphics
415 **/
416 /* fprintf(fd,"\033*rbC");*/
417 fprintf(fd, "\f\033@");
418 }
419
420
421
422
423
PicBuf_to_ESCP2(const GEN_PAR * pg,const OUT_PAR * po)424 int PicBuf_to_ESCP2(const GEN_PAR * pg, const OUT_PAR * po)
425 /**
426 ** Main interface routine
427 **/
428 {
429 FILE *fd = stdout;
430 RowBuf *row;
431 int row_c, i, x, color_index, offset, err;
432 Byte mask;
433 int width;
434
435 err = 0;
436 if (!pg->quiet)
437 Eprintf("\nWriting Esc/P2 output\n");
438 /*
439 if (po->picbuf->depth > 1 && po->specials < 3)
440 Eprintf ("\nWARNING: Monochrome output despite active colors selected!\n");
441
442 Deskjet_specials = (po->specials != 0) ? TRUE : FALSE;
443 */
444 /**
445 ** Allocate buffers for CMYK conversion
446 **/
447 if (po->picbuf->depth > 1) {
448 p_K = calloc((size_t) po->picbuf->nb, sizeof(Byte));
449 p_C = calloc((size_t) po->picbuf->nb, sizeof(Byte));
450 p_M = calloc((size_t) po->picbuf->nb, sizeof(Byte));
451 p_Y = calloc((size_t) po->picbuf->nb, sizeof(Byte));
452 if (p_K == NULL || p_C == NULL || p_M == NULL
453 || p_Y == NULL) {
454 Eprintf
455 ("\nCannot 'calloc' CMYK memory -- sorry, use B/W!\n");
456 goto ESCP2_exit;
457 }
458 }
459 /**
460 ** Optional memory; for compression
461 **/
462 n_B = B_EXTRASPACE;
463 p_B = calloc((size_t) (po->picbuf->nb + n_B), sizeof(Byte));
464
465
466 if (*po->outfile != '-') {
467 #ifdef VAX
468 if ((fd =
469 fopen(po->outfile, WRITE_BIN, "rfm=var",
470 "mrs=512")) == NULL) {
471 #else
472 if ((fd = fopen(po->outfile, WRITE_BIN)) == NULL) {
473 #endif
474 PError("hp2xx -- opening output file");
475 goto ESCP2_exit;
476 }
477 }
478
479 init_printer(po, fd);
480
481
482 /**
483 ** Loop for all rows:
484 ** Counting back since highest index is lowest line on paper...
485 **/
486 width = 8 * po->picbuf->nb; /*line width in pixels */
487
488 for (row_c = po->picbuf->nr - 1; row_c >= 0; row_c--) {
489 if ((!pg->quiet) && (row_c % 10 == 0))
490 /* For the impatients among us ... */
491 Eprintf(".");
492
493 row = get_RowBuf(po->picbuf, row_c);
494
495 if (po->picbuf->depth == 1) {
496 putc('\r', fd); /* move print head to start of line */
497 (void) fwrite("\033r\000", 3, 1, fd); /* set color black */
498 (void) fwrite("\033.\001\005\005\001", 6, 1, fd); /* announce RLE data */
499 putc(width & 255, fd); /*width of raster line in pixels */
500 putc(width >> 8, fd);
501 Buf_to_ESCP2(row->buf, po->picbuf->nb,
502 ESCP2_FIRST | ESCP2_LAST, fd);
503 (void) fwrite("\033(v\002\000\001\000", 7, 1, fd);
504 } else {
505 for (x = 0; x < po->picbuf->nb; x++)
506 p_K[x] = p_C[x] = p_M[x] = p_Y[x] = 0;
507
508 for (x = offset = 0; x < (po->picbuf->nb << 3);
509 x++, offset = (x >> 3)) {
510 color_index =
511 index_from_RowBuf(row, x, po->picbuf);
512
513 if (color_index == xxBackground)
514 continue;
515 else {
516 mask = 0x80;
517 if ((i = x & 0x07) != 0)
518 mask >>= i;
519
520 if (pt.clut[color_index][0] +
521 pt.clut[color_index][1] +
522 pt.clut[color_index][2] == 0) {
523 *(p_K + offset) |= mask;
524 } else {
525 *(p_C + offset) |=
526 (mask ^
527 (pt.
528 clut[color_index][0]
529 & mask));
530 *(p_M + offset) |=
531 (mask ^
532 (pt.
533 clut[color_index][1]
534 & mask));
535 *(p_Y + offset) |=
536 (mask ^
537 (pt.
538 clut[color_index][2]
539 & mask));
540 }
541 /*
542 switch (color_index)
543 {
544 case xxForeground:
545 *(p_K + offset) |= mask;
546 break;
547 case xxRed:
548 *(p_M + offset) |= mask;
549 *(p_Y + offset) |= mask;
550 break;
551 case xxGreen:
552 *(p_C + offset) |= mask;
553 *(p_Y + offset) |= mask;
554 break;
555 case xxBlue:
556 *(p_C + offset) |= mask;
557 *(p_M + offset) |= mask;
558 break;
559 case xxCyan:
560 *(p_C + offset) |= mask;
561 break;
562 case xxMagenta:
563 *(p_M + offset) |= mask;
564 break;
565 case xxYellow:
566 *(p_Y + offset) |= mask;
567 break;
568 default:
569 break;
570 }
571 */
572 }
573 }
574
575 /* switch (po->specials)
576 {
577 case 3:
578 K_to_CMY (po->picbuf->nb);
579 / * drop thru * /
580 case 4:
581 fprintf(stderr, "case 4: KCMY\n");
582 */
583 /*fprintf(stderr,"calculated width %d pixels, nb is %d (%d)\n",width,po->picbuf->nb,8*po->picbuf->nb);
584 */
585 KCMY_Buf_to_ESCP2(po->picbuf->nb,
586 (po->specials == 4), width, fd);
587 /* fprintf(stderr,"sent line %d from buffer\n",row_c);*/
588 (void) fwrite("\033(v\002\000\001\000", 7, 1, fd);
589 /*
590 break;
591 default:
592 KCMY_to_K (po->picbuf->nb);
593 Buf_to_ESCP2 (p_K, po->picbuf->nb, ESCP2_FIRST | ESCP2_LAST, fd);
594 break;
595 }
596 */
597 }
598 }
599 /*fprintf(stderr,"end graphmode\n");*/
600 end_graphmode(fd);
601 /* if (po->formfeed)
602 putc (FF, fd);*/
603 if (!pg->quiet)
604 Eprintf("\n");
605 if (fd != stdout)
606 fclose(fd);
607
608 ESCP2_exit:
609 if (p_Y != NULL)
610 free(p_Y);
611 if (p_M != NULL)
612 free(p_M);
613 if (p_C != NULL)
614 free(p_C);
615 if (p_K != NULL)
616 free(p_K);
617
618 if (p_B != NULL)
619 free(p_B);
620
621 p_K = p_C = p_M = p_Y = NULL;
622 return err;
623 }
624