386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / sfilter2.c
CommitLineData
b8c9f32e
WJ
1/* Copyright (C) 1991 Aladdin Enterprises. All rights reserved.
2 Distributed by Free Software Foundation, Inc.
3
4This file is part of Ghostscript.
5
6Ghostscript is distributed in the hope that it will be useful, but
7WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
8to anyone for the consequences of using it or for whether it serves any
9particular purpose or works at all, unless he says so in writing. Refer
10to the Ghostscript General Public License for full details.
11
12Everyone is granted permission to copy, modify and redistribute
13Ghostscript, but only under the conditions described in the Ghostscript
14General Public License. A copy of this license is supposed to have been
15given to you along with Ghostscript so you can know your rights and
16responsibilities. It should be in a file named COPYING. Among other
17things, the copyright notice and this notice must be preserved on all
18copies. */
19
20/* sfilter2.c */
21/* Additional stream functions for filters */
22#include <stdio.h>
23#include "memory_.h"
24#include "std.h"
25#include "scanchar.h"
26#include "stream.h"
27
28/* Generic functions in sfilter.c */
29extern int s_filter_flush(P1(stream *));
30extern int s_filter_close(P1(stream *));
31
32/* ------ ASCII85Encode ------ */
33
34/* Flush the buffer */
35private int
36s_A85E_write_buf(register stream *s)
37{ register stream *strm = s->strm;
38 register byte *p = s->cbuf;
39 register int count = s->cptr + 1 - p;
40 while ( count >= 4 )
41 { ulong word =
42 ((ulong)(((uint)p[0] << 8) + p[1]) << 16) +
43 (((uint)p[2] << 8) + p[3]);
44 if ( word == 0 )
45 sputc(strm, 'z');
46 else
47 { ulong q = word / (85L*85*85*85);
48 ushort w1;
49 sputc(strm, q + '!');
50 word -= q * (85L*85*85*85);
51 q = word / (85L*85*85);
52 sputc(strm, q + '!');
53 word -= q * (85L*85*85);
54 q = word / (85*85);
55 sputc(strm, q + '!');
56 w1 = (ushort)(word - q * (85L*85));
57 sputc(strm, w1 / 85 + '!');
58 sputc(strm, w1 % 85 + '!');
59 if ( !(count & 60) )
60 sputc(strm, '\n');
61 }
62 count -= 4, p += 4;
63 }
64 memcpy(s->cbuf, p, count);
65 s->cptr = s->cbuf + count - 1;
66 return 0;
67}
68
69/* Close the stream, flushing a partial word. */
70private int
71s_A85E_close(register stream *s)
72{ stream *strm = s->strm;
73 int count;
74 (*s->procs.write_buf)(s);
75 count = s->cptr - s->cbuf + 1;
76 if ( count > 0 )
77 { /* Handle leftover bytes. 1 <= count <= 3. */
78 /* All the bytes are at the beginning of the buffer. */
79 byte ebuf[5];
80 stream sst;
81 s->cptr[1] = s->cptr[2] = s->cptr[3] = 0xff;
82 s->cptr = s->cbuf + 3;
83 swrite_string(&sst, ebuf, 5);
84 s->strm = &sst;
85 (*s->procs.write_buf)(s); /* force out final codes */
86 sputs(strm, ebuf, count + 1);
87 }
88 sputs(strm, (byte *)"~>", 2);
89 return s_std_close(s);
90}
91
92/* Stream procedures */
93stream_procs s_A85E_procs =
94 { s_std_noavailable, NULL, s_filter_flush, s_A85E_close,
95 NULL, s_A85E_write_buf
96 };
97
98/* ------ ASCII85Decode ------ */
99
100/* Refill the buffer */
101private int
102s_A85D_read_buf(register stream *s)
103{ register stream *strm = s->strm;
104 register byte *p = s->cbuf;
105 byte *limit = p + s->bsize - 4;
106 int ccount = 0;
107 ulong word = 0;
108 while ( p < limit )
109 { int ch = sgetc(strm);
110 uint ccode = ch - '!';
111 if ( ccode < 85 ) /* catches ch < '!' as well */
112 { word = word * 85 + ccode;
113 if ( ++ccount == 5 )
114 { p[0] = word >> 24;
115 p[1] = (byte)(word >> 16);
116 p[2] = (byte)((uint)word >> 8);
117 p[3] = (byte)word;
118 p += 4;
119 word = 0;
120 ccount = 0;
121 }
122 }
123 else if ( ch == 'z' && ccount == 0 )
124 p[0] = p[1] = p[2] = p[3] = 0,
125 p += 4;
126 else if ( scan_char_decoder[ch] == ctype_space )
127 ;
128 else if ( ch == '~' && sgetc(strm) == '>' )
129 { /* Handle odd bytes */
130 s->end_status = EOFC;
131 switch ( ccount )
132 {
133 case 0:
134 break;
135 case 1: /* syntax error */
136 s->end_status = ERRC;
137 break;
138 case 2: /* 1 odd byte */
139 word = word * (85L+85*85) + 0xffffffL;
140 goto o1;
141 case 3: /* 2 odd bytes */
142 word = word * (85L*85) + 0xffffL;
143 goto o2;
144 case 4: /* 3 odd bytes */
145 word = word * 85 + 0xffL;
146 p[2] = (byte)(word >> 8);
147o2: p[1] = (byte)(word >> 16);
148o1: p[0] = (byte)(word >> 24);
149 p += ccount - 1;
150 }
151 break;
152 }
153 else /* syntax error */
154 { s->end_status = ERRC;
155 break;
156 }
157 }
158 s->cptr = s->cbuf - 1;
159 s->endptr = p - 1;
160 if ( !s->end_status ) s->end_status = strm->end_status;
161 return 0;
162}
163
164/* Stream procedures */
165stream_procs s_A85D_procs =
166 { s_std_noavailable, NULL, s_std_null, s_filter_close,
167 s_A85D_read_buf, NULL
168 };
169
170/* ------ NullEncode ------ */
171
172/* Flush the buffer */
173private int
174s_NullE_write_buf(register stream *s)
175{ sputs(s->strm, s->cbuf, s->cptr - s->cbuf + 1);
176 s->cptr = s->cbuf - 1;
177 return 0;
178}
179
180/* Close the stream */
181private int
182s_NullE_close(register stream *s)
183{ sflush(s);
184 return s_filter_close(s);
185}
186
187/* Stream procedures */
188stream_procs s_NullE_procs =
189 { s_std_noavailable, NULL, s_filter_flush, s_NullE_close,
190 NULL, s_NullE_write_buf
191 };
192
193/* ------ RunLengthEncode ------ */
194
195/* Initialize */
196void
197s_RLE_init(register stream *s, uint rec_size)
198{ s->record_size = (rec_size == 0 ? max_uint : rec_size);
199 s->record_left = s->record_size;
200}
201
202/* Empty the buffer */
203private int
204s_RLE_write_buf(register stream *s)
205{ register stream *strm = s->strm;
206 register byte *p = s->cbuf;
207 while ( p <= s->cptr )
208 { byte *beg = p, *q;
209 uint count = s->cptr - p + 1;
210 if ( count > s->record_left)
211 count = s->record_left;
212 if ( count > 127 )
213 count = 127;
214 q = p + count;
215 if ( count > 2 && p[1] == p[0] )
216 { /* Recognize leading repeated byte */
217 do { p++; }
218 while ( p + 1 < q && p[1] == p[0] );
219 p++;
220 sputc(strm, 257 - (p - beg));
221 sputc(strm, *beg);
222 }
223 else
224 { while ( p + 2 < q && (p[1] != p[0] || p[2] != p[0]) )
225 p++;
226 if ( p + 2 >= q ) p = q;
227 sputc(strm, p - beg - 1);
228 sputs(strm, beg, p - beg);
229 }
230 s->record_left -= p - beg;
231 if ( s->record_left == 0 )
232 s->record_left = s->record_size;
233 }
234 s->cptr = s->cbuf - 1;
235 return 0;
236}
237
238/* Close */
239private int
240s_RLE_close(register stream *s)
241{ (*s->procs.write_buf)(s);
242 sputc(s->strm, 128);
243 return s_std_close(s);
244}
245
246/* Stream procedures */
247stream_procs s_RLE_procs =
248 { s_std_noavailable, NULL, s_filter_flush, s_RLE_close,
249 NULL, s_RLE_write_buf
250 };
251
252/* ------ RunLengthDecode ------ */
253
254/* Initialize */
255void
256s_RLD_init(register stream *s)
257{ s->odd = -1;
258}
259
260/* Refill the buffer */
261private int
262s_RLD_read_buf(register stream *s)
263{ register stream *strm = s->strm;
264 register byte *p = s->cbuf;
265 byte *limit = p + s->bsize;
266 int b = s->odd;
267 if ( b < 0 ) b = sgetc(strm);
268 for ( ; ; )
269 { uint count;
270 if ( b < 0 ) break; /* EOF/ERR */
271 if ( b < 128 )
272 { if ( p + b >= limit ) break; /* data won't fit */
273 count = sgets(s, p, b + 1);
274 p += count;
275 b = -1;
276 if ( strm->end_status ) break; /* EOF/ERR */
277 }
278 else if ( b == 128 ) /* end of data */
279 { s->end_status = EOFC;
280 b = -1;
281 break;
282 }
283 else if ( p + (257 - b) > limit )
284 break; /* won't fit */
285 else
286 { count = 257 - b;
287 b = sgetc(strm);
288 if ( b < 0 ) break; /* EOF/ERR */
289 memset(p, b, count);
290 p += count;
291 }
292 b = sgetc(strm);
293 }
294 s->cptr = s->cbuf - 1;
295 s->endptr = p - 1;
296 s->odd = b;
297 if ( !s->end_status ) s->end_status = strm->end_status;
298 return 0;
299}
300
301/* Stream procedures */
302stream_procs s_RLD_procs =
303 { s_std_noavailable, NULL, s_std_null, s_std_close,
304 s_RLD_read_buf, NULL
305 };
306
307/* ------ SubFileDecode ------ */
308/* Currently equivalent to "NullDecode" */
309
310/* Refill the buffer */
311private int
312s_SFD_read_buf(register stream *s)
313{ stream *strm = s->strm;
314 uint count = sgets(strm, s->cbuf, s->bsize);
315 s->cptr = s->cbuf - 1;
316 s->endptr = s->cptr + count;
317 s->end_status = strm->end_status;
318 return count;
319}
320
321/* Stream procedures */
322stream_procs s_SFD_procs =
323 { s_std_noavailable, NULL, s_std_null, s_filter_close,
324 s_SFD_read_buf, NULL
325 };