17dd7cddfSDavid du Colombier /* Copyright (C) 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
27dd7cddfSDavid du Colombier
3*593dc095SDavid du Colombier This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier implied.
57dd7cddfSDavid du Colombier
6*593dc095SDavid du Colombier This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier
10*593dc095SDavid du Colombier For more information about licensing, please refer to
11*593dc095SDavid du Colombier http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier San Rafael, CA 94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier
17*593dc095SDavid du Colombier /* $Id: srld.c,v 1.4 2002/02/21 22:24:54 giles Exp $ */
187dd7cddfSDavid du Colombier /* RunLengthDecode filter */
197dd7cddfSDavid du Colombier #include "stdio_.h" /* includes std.h */
207dd7cddfSDavid du Colombier #include "memory_.h"
217dd7cddfSDavid du Colombier #include "strimpl.h"
227dd7cddfSDavid du Colombier #include "srlx.h"
237dd7cddfSDavid du Colombier
247dd7cddfSDavid du Colombier /* ------ RunLengthDecode ------ */
257dd7cddfSDavid du Colombier
267dd7cddfSDavid du Colombier private_st_RLD_state();
277dd7cddfSDavid du Colombier
287dd7cddfSDavid du Colombier /* Set defaults */
297dd7cddfSDavid du Colombier private void
s_RLD_set_defaults(stream_state * st)307dd7cddfSDavid du Colombier s_RLD_set_defaults(stream_state * st)
317dd7cddfSDavid du Colombier {
327dd7cddfSDavid du Colombier stream_RLD_state *const ss = (stream_RLD_state *) st;
337dd7cddfSDavid du Colombier
347dd7cddfSDavid du Colombier s_RLD_set_defaults_inline(ss);
357dd7cddfSDavid du Colombier }
367dd7cddfSDavid du Colombier
377dd7cddfSDavid du Colombier /* Initialize */
387dd7cddfSDavid du Colombier private int
s_RLD_init(stream_state * st)397dd7cddfSDavid du Colombier s_RLD_init(stream_state * st)
407dd7cddfSDavid du Colombier {
417dd7cddfSDavid du Colombier stream_RLD_state *const ss = (stream_RLD_state *) st;
427dd7cddfSDavid du Colombier
437dd7cddfSDavid du Colombier return s_RLD_init_inline(ss);
447dd7cddfSDavid du Colombier }
457dd7cddfSDavid du Colombier
467dd7cddfSDavid du Colombier /* Refill the buffer */
477dd7cddfSDavid du Colombier private int
s_RLD_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)487dd7cddfSDavid du Colombier s_RLD_process(stream_state * st, stream_cursor_read * pr,
497dd7cddfSDavid du Colombier stream_cursor_write * pw, bool last)
507dd7cddfSDavid du Colombier {
517dd7cddfSDavid du Colombier stream_RLD_state *const ss = (stream_RLD_state *) st;
527dd7cddfSDavid du Colombier register const byte *p = pr->ptr;
537dd7cddfSDavid du Colombier register byte *q = pw->ptr;
547dd7cddfSDavid du Colombier const byte *rlimit = pr->limit;
557dd7cddfSDavid du Colombier byte *wlimit = pw->limit;
567dd7cddfSDavid du Colombier int left;
577dd7cddfSDavid du Colombier int status = 0;
587dd7cddfSDavid du Colombier
597dd7cddfSDavid du Colombier top:
607dd7cddfSDavid du Colombier if ((left = ss->copy_left) > 0) {
617dd7cddfSDavid du Colombier /*
627dd7cddfSDavid du Colombier * We suspended because the output buffer was full:;
637dd7cddfSDavid du Colombier * try again now.
647dd7cddfSDavid du Colombier */
657dd7cddfSDavid du Colombier uint avail = wlimit - q;
667dd7cddfSDavid du Colombier int copy_status = 1;
677dd7cddfSDavid du Colombier
687dd7cddfSDavid du Colombier if (left > avail)
697dd7cddfSDavid du Colombier left = avail;
707dd7cddfSDavid du Colombier if (ss->copy_data >= 0)
717dd7cddfSDavid du Colombier memset(q + 1, ss->copy_data, left);
727dd7cddfSDavid du Colombier else {
737dd7cddfSDavid du Colombier avail = rlimit - p;
747dd7cddfSDavid du Colombier if (left >= avail) {
757dd7cddfSDavid du Colombier copy_status = 0;
767dd7cddfSDavid du Colombier left = avail;
777dd7cddfSDavid du Colombier }
787dd7cddfSDavid du Colombier memcpy(q + 1, p + 1, left);
797dd7cddfSDavid du Colombier p += left;
807dd7cddfSDavid du Colombier }
817dd7cddfSDavid du Colombier q += left;
827dd7cddfSDavid du Colombier if ((ss->copy_left -= left) > 0) {
837dd7cddfSDavid du Colombier status = copy_status;
847dd7cddfSDavid du Colombier goto x;
857dd7cddfSDavid du Colombier }
867dd7cddfSDavid du Colombier }
877dd7cddfSDavid du Colombier while (p < rlimit) {
887dd7cddfSDavid du Colombier int b = *++p;
897dd7cddfSDavid du Colombier
907dd7cddfSDavid du Colombier if (b < 128) {
917dd7cddfSDavid du Colombier if (++b > rlimit - p || b > wlimit - q) {
927dd7cddfSDavid du Colombier ss->copy_left = b;
937dd7cddfSDavid du Colombier ss->copy_data = -1;
947dd7cddfSDavid du Colombier goto top;
957dd7cddfSDavid du Colombier }
967dd7cddfSDavid du Colombier memcpy(q + 1, p + 1, b);
977dd7cddfSDavid du Colombier p += b;
987dd7cddfSDavid du Colombier q += b;
997dd7cddfSDavid du Colombier } else if (b == 128) { /* end of data */
1007dd7cddfSDavid du Colombier if (ss->EndOfData) {
1017dd7cddfSDavid du Colombier status = EOFC;
1027dd7cddfSDavid du Colombier break;
1037dd7cddfSDavid du Colombier }
1047dd7cddfSDavid du Colombier } else if (p == rlimit) {
1057dd7cddfSDavid du Colombier p--;
1067dd7cddfSDavid du Colombier break;
1077dd7cddfSDavid du Colombier } else if ((b = 257 - b) > wlimit - q) {
1087dd7cddfSDavid du Colombier ss->copy_left = b;
1097dd7cddfSDavid du Colombier ss->copy_data = *++p;
1107dd7cddfSDavid du Colombier goto top;
1117dd7cddfSDavid du Colombier } else {
1127dd7cddfSDavid du Colombier memset(q + 1, *++p, b);
1137dd7cddfSDavid du Colombier q += b;
1147dd7cddfSDavid du Colombier }
1157dd7cddfSDavid du Colombier }
1167dd7cddfSDavid du Colombier x: pr->ptr = p;
1177dd7cddfSDavid du Colombier pw->ptr = q;
1187dd7cddfSDavid du Colombier return status;
1197dd7cddfSDavid du Colombier }
1207dd7cddfSDavid du Colombier
1217dd7cddfSDavid du Colombier /* Stream template */
1227dd7cddfSDavid du Colombier const stream_template s_RLD_template = {
1237dd7cddfSDavid du Colombier &st_RLD_state, s_RLD_init, s_RLD_process, 1, 1, NULL,
1247dd7cddfSDavid du Colombier s_RLD_set_defaults
1257dd7cddfSDavid du Colombier };
126