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