1 /*
2  * TransFig: Facility for Translating Fig code
3  *
4  * (C) Thomas Merz 1994-2002
5  * Used with permission 19-03-2002
6  *
7  * Any party obtaining a copy of these files is granted, free of charge, a
8  * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
9  * nonexclusive right and license to deal in this software and
10  * documentation files (the "Software"), including without limitation the
11  * rights to use, copy, modify, merge, publish and/or distribute copies of
12  * the Software, and to permit persons who receive copies from any such
13  * party to do so, with the only requirement being that this copyright
14  * notice remain intact.
15  *
16  */
17 
18 /* ASCII85 and Hex encoding for PostScript Level 2 and PDF */
19 
20 #include "fig2dev.h"
21 #include "psimage.h"
22 
23 typedef unsigned char byte;
24 
25 static unsigned char buf[4];
26 static unsigned long power85[5] = { 1L, 85L, 85L*85, 85L*85*85, 85L*85*85*85};
27 static int outbytes;		/* Number of characters in an output line */
28 
29 /* read 0-4 Bytes. result: number of bytes read */
30 static int
ReadSomeBytes(FILE * in)31 ReadSomeBytes(FILE * in)
32 {
33   register int count, i;
34 
35   for (count = 0; count < 4; count++) {
36     if ((i = getc(in)) == EOF)
37       break;
38     else
39       buf[count] = (byte) i;
40   }
41   return count;
42 }
43 
44 /* Two percent characters at the start of a line will cause trouble
45  * with some post-processing software. In order to avoid this, we
46  * simply insert a line break if we encounter a percent character
47  * at the start of the line. Of course, this rather simplistic
48  * algorithm may lead to a large line count in pathological cases,
49  * but the chance for hitting such a case is very small, and even
50  * so it's only a cosmetic flaw and not a functional restriction.
51  */
52 
53 static void
outbyte(byte c,FILE * out)54 outbyte(byte c, FILE * out)
55 {    /* output one byte */
56 
57   if (fputc(c, out) == EOF) {
58     fprintf(stderr, "jpeg2ps: write error - exit!\n");
59     exit(1);
60   }
61 
62   if (++outbytes > 63 ||		/* line limit reached */
63     (outbytes == 1 && c == '%') ) {	/* caution: percent character at start of line */
64     fputc('\n', out);			/* insert line feed */
65     outbytes = 0;
66   }
67 }
68 
69 int
ASCII85Encode(FILE * in,FILE * out)70 ASCII85Encode(FILE * in, FILE * out)
71 {
72   register int i, count;
73   unsigned long word, v;
74 
75   outbytes = 0;
76 
77   /* 4 bytes read ==> output 5 bytes */
78   while ((count = ReadSomeBytes(in)) == 4) {
79     word = ((unsigned long)(((unsigned int)buf[0] << 8) + buf[1]) << 16) +
80                    (((unsigned int)buf[2] << 8) + buf[3]);
81     if (word == 0)
82       outbyte('z', out);       /* shortcut for 0 */
83     else
84       /* calculate 5 ASCII85 bytes and output them */
85       for (i = 4; i >= 0; i--) {
86 	v = word / power85[i];
87 	outbyte((byte) (v + '!'), out);
88 	word -= v * power85[i];
89       }
90   }
91 
92   word = 0;
93 
94   if (count != 0) {   /* 1-3 bytes left */
95     for (i = count-1; i >= 0; i--)   /* accumulate bytes */
96       word += (unsigned long)buf[i] << 8 * (3-i);
97 
98     /* encoding as above, but output only count+1 bytes */
99     for (i = 4; i >= 4-count; i--) {
100       v = word / power85[i];
101       outbyte((byte) (v + '!'), out);
102       word -= v * power85[i];
103     }
104   }
105 
106   fputc('~', out);	/* EOD marker */
107   fputc('>', out);
108   return 0;
109 }
110 
111 void
ASCIIHexEncode(FILE * in,FILE * out)112 ASCIIHexEncode(FILE *in, FILE * out) {
113   static char buffer[512];
114   static char BinToHex[] = "0123456789ABCDEF";
115   int CharsPerLine;
116   size_t i, n;
117   unsigned char *p;
118 
119   CharsPerLine = 0;
120   fputc('\n', out);
121 
122   while ((n = fread(buffer, 1, sizeof(buffer), in)) != 0)
123     for (i = 0, p = (unsigned char *) buffer; i < n; i++, p++) {
124       fputc(BinToHex[*p>>4], out);           /* first nibble  */
125       fputc(BinToHex[*p & 0x0F], out);       /* second nibble */
126       if ((CharsPerLine += 2) >= 64) {
127         fputc('\n', out);
128         CharsPerLine = 0;
129       }
130     }
131 
132   fputc('>', out);         /* EOD marker for PostScript hex strings */
133 }
134 
135