Commit | Line | Data |
---|---|---|
b8c9f32e WJ |
1 | /* Copyright (C) 1991 Aladdin Enterprises. All rights reserved. |
2 | Distributed by Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of Ghostscript. | |
5 | ||
6 | Ghostscript is distributed in the hope that it will be useful, but | |
7 | WITHOUT ANY WARRANTY. No author or distributor accepts responsibility | |
8 | to anyone for the consequences of using it or for whether it serves any | |
9 | particular purpose or works at all, unless he says so in writing. Refer | |
10 | to the Ghostscript General Public License for full details. | |
11 | ||
12 | Everyone is granted permission to copy, modify and redistribute | |
13 | Ghostscript, but only under the conditions described in the Ghostscript | |
14 | General Public License. A copy of this license is supposed to have been | |
15 | given to you along with Ghostscript so you can know your rights and | |
16 | responsibilities. It should be in a file named COPYING. Among other | |
17 | things, the copyright notice and this notice must be preserved on all | |
18 | copies. */ | |
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 */ | |
29 | extern int s_filter_flush(P1(stream *)); | |
30 | extern int s_filter_close(P1(stream *)); | |
31 | ||
32 | /* ------ ASCII85Encode ------ */ | |
33 | ||
34 | /* Flush the buffer */ | |
35 | private int | |
36 | s_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. */ | |
70 | private int | |
71 | s_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 */ | |
93 | stream_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 */ | |
101 | private int | |
102 | s_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); | |
147 | o2: p[1] = (byte)(word >> 16); | |
148 | o1: 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 */ | |
165 | stream_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 */ | |
173 | private int | |
174 | s_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 */ | |
181 | private int | |
182 | s_NullE_close(register stream *s) | |
183 | { sflush(s); | |
184 | return s_filter_close(s); | |
185 | } | |
186 | ||
187 | /* Stream procedures */ | |
188 | stream_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 */ | |
196 | void | |
197 | s_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 */ | |
203 | private int | |
204 | s_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 */ | |
239 | private int | |
240 | s_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 */ | |
247 | stream_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 */ | |
255 | void | |
256 | s_RLD_init(register stream *s) | |
257 | { s->odd = -1; | |
258 | } | |
259 | ||
260 | /* Refill the buffer */ | |
261 | private int | |
262 | s_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 */ | |
302 | stream_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 */ | |
311 | private int | |
312 | s_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 */ | |
322 | stream_procs s_SFD_procs = | |
323 | { s_std_noavailable, NULL, s_std_null, s_filter_close, | |
324 | s_SFD_read_buf, NULL | |
325 | }; |