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