diff options
Diffstat (limited to 'Build/source/utils/sam2p/pts_fax.c')
-rw-r--r-- | Build/source/utils/sam2p/pts_fax.c | 3221 |
1 files changed, 3221 insertions, 0 deletions
diff --git a/Build/source/utils/sam2p/pts_fax.c b/Build/source/utils/sam2p/pts_fax.c new file mode 100644 index 00000000000..39a1f6819eb --- /dev/null +++ b/Build/source/utils/sam2p/pts_fax.c @@ -0,0 +1,3221 @@ +/* + * pts_fax.c -- a compact CCITTFax compressor and uncompressor) implementation + * compiled by pts@fazekas.hu at Sun Jul 7 19:51:42 CEST 2002 + * + * algorithm ripped from GNU Ghostscript, implementation and (C): + * +Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All +rights reserved. + +GNU Ghostscript is free software; you can redistribute it and/or +modify it under the terms of version 2 of the GNU General Public +License as published by the Free Software Foundation. + +GNU Ghostscript is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty +of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program so you can know your rights and responsibilities. +It should be in a file named doc/COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place Suite 330, Boston, MA +02111-1307, USA. + */ + +#include "pts_fax.h" +#if 0 /* doesn't work in C++ */ +# define intern static +# define impl static +# define intern_const static const +# define impl_const static const +#else +# define intern static +# define impl static +# define intern_const extern const +# define impl_const const +#endif +/* #define cxxintern extern */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +/* misc_types.h by pts@fazekas.hu at Sat Jul 6 19:20:17 CEST 2002 */ +#ifndef MISC_TYPES_H +#define MISC_TYPES_H 1 + +/* #include "config2.h" */ + +#define BEGIN do { +#define END } while (0) +#ifndef DO_NOTHING +# define DO_NOTHING BEGIN END +#endif + +# define if_debug0(c,s) DO_NOTHING +# define if_debug1(c,s,a1) DO_NOTHING +# define if_debug2(c,s,a1,a2) DO_NOTHING +# define if_debug3(c,s,a1,a2,a3) DO_NOTHING +# define if_debug4(c,s,a1,a2,a3,a4) DO_NOTHING +# define if_debug5(c,s,a1,a2,a3,a4,a5) DO_NOTHING +# define if_debug6(c,s,a1,a2,a3,a4,a5,a6) DO_NOTHING +# define if_debug7(c,s,a1,a2,a3,a4,a5,a6,a7) DO_NOTHING +# define if_debug8(c,s,a1,a2,a3,a4,a5,a6,a7,a8) DO_NOTHING +# define if_debug9(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9) DO_NOTHING +# define if_debug10(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) DO_NOTHING +# define if_debug11(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) DO_NOTHING +# define if_debug12(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) DO_NOTHING + +/* to the one that all the compilers seem to have.... */ +#ifndef min +# define min(a, b) (((a) < (b)) ? (a) : (b)) +#endif +#ifndef max +# define max(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +/* Define a standard way to round values to a (constant) modulus. */ +#define ROUND_DOWN(value, modulus)\ + ( (modulus) & ((modulus) - 1) ? /* not a power of 2 */\ + (value) - (value) % (modulus) :\ + (value) & -(modulus) ) +#define ROUND_UP(value, modulus)\ + ( (modulus) & ((modulus) - 1) ? /* not a power of 2 */\ + ((value) + ((modulus) - 1)) / (modulus) * (modulus) :\ + ((value) + ((modulus) - 1)) & -(modulus) ) + +#define countof(a) (sizeof(a) / sizeof((a)[0])) + +#define gs_alloc_bytes(a, n, c) ss->xalloc_(n) +#define gs_free_object(a, ptr, c) ss->free_(ptr) + +#endif /* gstypes.h */ +/* end of former misc_types.h */ + +/* gsbittab.h */ +/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */ +/* Interface to tables for bit operations */ + +#ifndef gsbittab_INCLUDED +# define gsbittab_INCLUDED + +/* + * Generate tables for transforming 2, 4, 6, or 8 bits. + */ +#define btab2_(v0,v2,v1)\ + v0,v1+v0,v2+v0,v2+v1+v0 +#define bit_table_2(v0,v2,v1) btab2_(v0,v2,v1) +#define btab4_(v0,v8,v4,v2,v1)\ + btab2_(v0,v2,v1), btab2_(v4+v0,v2,v1),\ + btab2_(v8+v0,v2,v1), btab2_(v8+v4+v0,v2,v1) +#define bit_table_4(v0,v8,v4,v2,v1) btab4_(v0,v8,v4,v2,v1) +#define btab6_(v0,v20,v10,v8,v4,v2,v1)\ + btab4_(v0,v8,v4,v2,v1), btab4_(v10+v0,v8,v4,v2,v1),\ + btab4_(v20+v0,v8,v4,v2,v1), btab4_(v20+v10+v0,v8,v4,v2,v1) +#define bit_table_6(v0,v20,v10,v8,v4,v2,v1) btab6_(v0,v20,v10,v8,v4,v2,v1) +#define bit_table_8(v0,v80,v40,v20,v10,v8,v4,v2,v1)\ + btab6_(v0,v20,v10,v8,v4,v2,v1), btab6_(v40+v0,v20,v10,v8,v4,v2,v1),\ + btab6_(v80+v0,v20,v10,v8,v4,v2,v1), btab6_(v80+v40+v0,v20,v10,v8,v4,v2,v1) + +/* + * byte_reverse_bits[B] = the unsigned char B with the order of bits reversed. + */ +intern_const unsigned char byte_reverse_bits[256]; + +/* + * byte_right_mask[N] = a unsigned char with N trailing 1s, 0 <= N <= 8. + */ +intern_const unsigned char byte_right_mask[9]; + +/* + * byte_count_bits[B] = the number of 1-bits in a unsigned char with value B. + */ +intern_const unsigned char byte_count_bits[256]; + +/* + * byte_bit_run_length_N[B], for 0 <= N <= 7, gives the length of the + * run of 1-bits starting at bit N in a unsigned char with value B, + * numbering the bits in the unsigned char as 01234567. If the run includes + * the low-order bit (i.e., might be continued into a following unsigned char), + * the run length is increased by 8. + */ +intern_const unsigned char + byte_bit_run_length_0[256], byte_bit_run_length_1[256], + byte_bit_run_length_2[256], byte_bit_run_length_3[256], + byte_bit_run_length_4[256], byte_bit_run_length_5[256], + byte_bit_run_length_6[256], byte_bit_run_length_7[256]; + +/* + * byte_bit_run_length[N] points to byte_bit_run_length_N. + * byte_bit_run_length_neg[N] = byte_bit_run_length[-N & 7]. + */ +intern_const unsigned char *const byte_bit_run_length[8]; +intern_const unsigned char *const byte_bit_run_length_neg[8]; + +/* + * byte_acegbdfh_to_abcdefgh[acegbdfh] = abcdefgh, where the letters + * denote the individual bits of the unsigned char. + */ +intern_const unsigned char byte_acegbdfh_to_abcdefgh[256]; + +#endif /* gsbittab_INCLUDED */ + +/* end of former gsbittab.h */ + +/* shc.h */ +/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */ +/* Common definitions for filters using Huffman coding */ + +#ifndef shc_INCLUDED +# define shc_INCLUDED + +/* #include "gsbittab.h" */ + +#define hc_bits_size (SIZEOF_INT * 8) +#define s_hce_init_inline(ss)\ + ((ss)->bits = 0, (ss)->bits_left = hc_bits_size) +#define s_hcd_init_inline(ss)\ + ((ss)->bits = 0, (ss)->bits_left = 0) + +/* + * These definitions are valid for code lengths up to 16 bits + * and non-negative decoded values up to 15 bits. + * + * We define 3 different representations of the code: encoding tables, + * decoding tables, and a definition table which can be generated easily + * from frequency information and which in turn can easily generate + * the encoding and decoding tables. + * + * The definition table has two parts: a list of the number of i-bit + * codes for each i >= 1, and the decoded values corresponding to + * the code values in increasing lexicographic order (which will also + * normally be decreasing code frequency). Calling these two lists + * L[1..M] and V[0..N-1] respectively, we have the following invariants: + * - 1 <= M <= max_hc_length, N >= 2. + * - L[0] = 0. + * - for i=1..M, L[i] >= 0. + * - sum(i=1..M: L[i]) = N. + * - sum(i=1..M: L[i] * 2^-i) = 1. + * - V[0..N-1] are a permutation of the integers 0..N-1. + */ +#define max_hc_length 16 +typedef struct hc_definition_s { + unsigned short *counts; /* [0..M] */ + unsigned int num_counts; /* M */ + unsigned short *values; /* [0..N-1] */ + unsigned int num_values; /* N */ +} hc_definition; + +/**** pts ****/ +struct stream_hc_state_s; +/* definition moved to pts_fax.h */ + +/* ------ Encoding tables ------ */ + +/* Define the structure for the encoding tables. */ +typedef struct hce_code_s { + unsigned short code; + unsigned short code_length; +} hce_code; + +#define hce_entry(c, len) { c, len } + +typedef struct hce_table_s { + unsigned int count; + hce_code *codes; +} hce_table; + +#define hce_bits_available(n)\ + (ss->bits_left >= (n) || wlimit - q > ((n) - ss->bits_left - 1) >> 3) + +/* ------ Encoding utilities ------ */ + +/* + * Put a code on the output. The client is responsible for ensuring + * that q does not exceed pw->limit. + */ + +#ifdef DEBUG +# define hc_print_value(code, clen)\ + (gs_debug_c('W') ?\ + (dlprintf2("[W]0x%x,%d\n", code, clen), 0) : 0) +# define hc_print_value_then(code, clen) hc_print_value(code, clen), +#else +# define hc_print_value(code, clen) 0 +# define hc_print_value_then(code, clen) /* */ +#endif +#define hc_print_code(rp) hc_print_value((rp)->code, (rp)->code_length) + +/* Declare variables that hold the encoder state. */ +#define hce_declare_state\ + register unsigned int bits;\ + register int bits_left + +/* Load the state from the stream. */ +/* Free variables: ss, bits, bits_left. */ +#define hce_load_state()\ + bits = ss->bits, bits_left = ss->bits_left + +/* Store the state back in the stream. */ +/* Free variables: ss, bits, bits_left. */ +#define hce_store_state()\ + ss->bits = bits, ss->bits_left = bits_left + +/* Put a code on the stream. */ +intern void hc_put_code_proc _((bool, unsigned char *, unsigned int)); + +#define hc_put_value(ss, q, code, clen)\ + (hc_print_value_then(code, clen)\ + ((bits_left -= (clen)) >= 0 ?\ + (bits += (code) << bits_left) :\ + (hc_put_code_proc((ss)->FirstBitLowOrder,\ + q += hc_bits_size >> 3,\ + (bits + ((code) >> -bits_left))),\ + bits = (code) << (bits_left += hc_bits_size)))) +#define hc_put_code(ss, q, cp)\ + hc_put_value(ss, q, (cp)->code, (cp)->code_length) + +/* + * Force out the final bits to the output. + * Note that this does a store_state, but not a load_state. + */ +intern unsigned char *hc_put_last_bits_proc _((struct stream_hc_state_s *, unsigned char *, unsigned int, int)); + +#define hc_put_last_bits(ss, q)\ + hc_put_last_bits_proc(ss, q, bits, bits_left) + +/* ------ Decoding tables ------ */ + +/* + * Define the structure for the decoding tables. + * First-level nodes are either leaves, which have + * value = decoded value + * code_length <= initial_bits + * or non-leaves, which have + * value = the index of a sub-table + * code_length = initial_bits + the number of additional dispatch bits + * Second-level nodes are always leaves, with + * code_length = the actual number of bits in the code - initial_bits. + */ + +typedef struct hcd_code_s { + short value; + unsigned short code_length; +} hcd_code; + +typedef struct hcd_table_s { + unsigned int count; + unsigned int initial_bits; + hcd_code *codes; +} hcd_table; + +/* Declare variables that hold the decoder state. */ +#define hcd_declare_state\ + register const unsigned char *p;\ + const unsigned char *rlimit;\ + unsigned int bits;\ + int bits_left + +/* Load the state from the stream. */ +/* Free variables: pr, ss, p, rlimit, bits, bits_left. */ +#define hcd_load_state()\ + p = pr->ptr,\ + rlimit = pr->limit,\ + bits = ss->bits,\ + bits_left = ss->bits_left + +/* Store the state back in the stream. */ +/* Put back any complete bytes into the input buffer. */ +/* Free variables: pr, ss, p, bits, bits_left. */ +#define hcd_store_state()\ + pr->ptr = p -= (bits_left >> 3),\ + ss->bits = bits >>= (bits_left & ~7),\ + ss->bits_left = bits_left &= 7 + +/* Macros to get blocks of bits from the input stream. */ +/* Invariants: 0 <= bits_left <= bits_size; */ +/* bits [bits_left-1..0] contain valid data. */ + +#define hcd_bits_available(n)\ + (bits_left >= (n) || rlimit - p > ((n) - bits_left - 1) >> 3) +/* For hcd_ensure_bits, n must not be greater than 8. */ +#define HCD_ENSURE_BITS_ELSE(n)\ + if (bits_left >= n)\ + DO_NOTHING;\ + else HCD_MORE_BITS_ELSE +#define hcd_ensure_bits(n, outl)\ + BEGIN HCD_ENSURE_BITS_ELSE(n) goto outl; END + +/* Load more bits into the buffer. */ +#define HCD_MORE_BITS_1_ELSE\ + if (p < rlimit) {\ + int c = *++p;\ +\ + if (ss->FirstBitLowOrder)\ + c = byte_reverse_bits[c];\ + bits = (bits << 8) + c, bits_left += 8;\ + } else +#if hc_bits_size == 16 +# define HCD_MORE_BITS_ELSE HCD_MORE_BITS_1_ELSE +#else /* hc_bits_size >= 32 */ +# define HCD_MORE_BITS_ELSE\ + if (rlimit - p >= 3) {\ + if (ss->FirstBitLowOrder)\ + bits = (bits << 24) + ((unsigned int)byte_reverse_bits[p[1]] << 16) + ((unsigned int)byte_reverse_bits[p[2]] << 8) + byte_reverse_bits[p[3]];\ + else\ + bits = (bits << 24) + ((unsigned int)p[1] << 16) + ((unsigned int)p[2] << 8) + p[3];\ + bits_left += 24, p += 3;\ + } else HCD_MORE_BITS_1_ELSE +#endif +#define hcd_more_bits(outl)\ + BEGIN HCD_MORE_BITS_ELSE goto outl; END + +#define hcd_peek_bits(n) ((bits >> (bits_left - (n))) & ((1 << (n)) - 1)) + +/* hcd_peek_var_bits requires bits_left <= 8. */ +#define hcd_peek_var_bits(n)\ + ((bits >> (bits_left - (n))) & byte_right_mask[n]) + +/* hcd_peek_bits_left requires bits_left <= 8. */ +#define hcd_peek_bits_left()\ + (bits & byte_right_mask[bits_left]) + +#define hcd_skip_bits(n) (bits_left -= (n)) + +#endif /* shc_INCLUDED */ + +/* end of former shc.h */ + +/* scf.h */ +/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */ +/* Common definitions for CCITTFax encoding and decoding filters */ + +#ifndef scf_INCLUDED +# define scf_INCLUDED + +/* #include "shc.h" */ + +/* + * The CCITT Group 3 (T.4) and Group 4 (T.6) fax specifications map + * run lengths to Huffman codes. White and black have different mappings. + * If the run length is 64 or greater, two or more codes are needed: + * - One or more 'make-up' codes for 2560 pixels; + * - A 'make-up' code that encodes the multiple of 64; + * - A 'termination' code for the remainder. + * For runs of 63 or less, only the 'termination' code is needed. + */ + +/* ------ Encoding tables ------ */ + +/* + * The maximum possible length of a scan line is determined by the + * requirement that 3 runs have to fit into the stream buffer. + * A run of length N requires approximately ceil(N / 2560) makeup codes, + * hence 1.5 * ceil(N / 2560) bytes. Taking the largest safe stream + * buffer size as 32K, we arrive at the following maximum width: + */ +#if SIZEOF_INT > 2 +# define cfe_max_width (2560 * 32000 * 2 / 3) +#else +# define cfe_max_width (max_int - 40) /* avoid overflows */ +#endif +/* The +5 in cfe_max_code_bytes is a little conservative. */ +#define cfe_max_code_bytes(width) ((width) / 2560 * 3 / 2 + 5) + +typedef hce_code cfe_run; + +/* Codes common to 1-D and 2-D encoding. */ +/* The decoding algorithms know that EOL is 0....01. */ +#define run_eol_code_length 12 +#define run_eol_code_value 1 +intern_const cfe_run cf_run_eol; +typedef struct cf_runs_s { + cfe_run termination[64]; + cfe_run make_up[41]; +} cf_runs; +intern_const cf_runs + cf_white_runs, cf_black_runs; +intern_const cfe_run cf_uncompressed[6]; +intern_const cfe_run cf_uncompressed_exit[10]; /* indexed by 2 x length of */ + + /* white run + (1 if next run black, 0 if white) */ +/* 1-D encoding. */ +intern_const cfe_run cf1_run_uncompressed; + +/* 2-D encoding. */ +intern_const cfe_run cf2_run_pass; + +#define cf2_run_pass_length 4 +#define cf2_run_pass_value 0x1 +#define cf2_run_vertical_offset 3 +intern_const cfe_run cf2_run_vertical[7]; /* indexed by b1 - a1 + offset */ +intern_const cfe_run cf2_run_horizontal; + +#define cf2_run_horizontal_value 1 +#define cf2_run_horizontal_length 3 +intern_const cfe_run cf2_run_uncompressed; + +/* 2-D Group 3 encoding. */ +intern_const cfe_run cf2_run_eol_1d; +intern_const cfe_run cf2_run_eol_2d; + +/* ------ Decoding tables ------ */ + +typedef hcd_code cfd_node; + +#define run_length value + +/* + * The value in the decoding tables is either a white or black run length, + * or a (negative) exceptional value. + */ +#define run_error (-1) +#define run_zeros (-2) /* EOL follows, possibly with more padding first */ +#define run_uncompressed (-3) +/* 2-D codes */ +#define run2_pass (-4) +#define run2_horizontal (-5) + +#define cfd_white_initial_bits 8 +#define cfd_white_min_bits 4 /* shortest white run */ +/* intern_const cfd_node cf_white_decode[]; */ + +#define cfd_black_initial_bits 7 +#define cfd_black_min_bits 2 /* shortest black run */ +/* intern_const cfd_node cf_black_decode[]; */ + +#define cfd_2d_initial_bits 7 +#define cfd_2d_min_bits 4 /* shortest non-H/V 2-D run */ +/* intern_const cfd_node cf_2d_decode[]; */ + +#define cfd_uncompressed_initial_bits 6 /* must be 6 */ +/* intern_const cfd_node cf_uncompressed_decode[]; */ + +/* ------ Run detection macros ------ */ + +/* + * For the run detection macros: + * white_byte is 0 or 0xff for BlackIs1 or !BlackIs1 respectively; + * data holds p[-1], inverted if !BlackIs1; + * count is the number of valid bits remaining in the scan line. + */ + +/* Aliases for bit processing tables. */ +#define cf_byte_run_length byte_bit_run_length_neg +#define cf_byte_run_length_0 byte_bit_run_length_0 + +/* Skip over white pixels to find the next black pixel in the input. */ +/* Store the run length in rlen, and update data, p, and count. */ +/* There are many more white pixels in typical input than black pixels, */ +/* and the runs of white pixels tend to be much longer, so we use */ +/* substantially different loops for the two cases. */ + +#define skip_white_pixels(data, p, count, white_byte, rlen)\ +BEGIN\ + rlen = cf_byte_run_length[count & 7][data ^ 0xff];\ + if ( rlen >= 8 ) { /* run extends past unsigned char boundary */\ + if ( white_byte == 0 ) {\ + if ( p[0] ) { data = p[0]; p += 1; rlen -= 8; }\ + else if ( p[1] ) { data = p[1]; p += 2; }\ + else {\ + while ( !(p[2] | p[3] | p[4] | p[5]) )\ + p += 4, rlen += 32;\ + if ( p[2] ) {\ + data = p[2]; p += 3; rlen += 8;\ + } else if ( p[3] ) {\ + data = p[3]; p += 4; rlen += 16;\ + } else if ( p[4] ) {\ + data = p[4]; p += 5; rlen += 24;\ + } else /* p[5] */ {\ + data = p[5]; p += 6; rlen += 32;\ + }\ + }\ + } else {\ + if ( p[0] != 0xff ) { data = (unsigned char)~p[0]; p += 1; rlen -= 8; }\ + else if ( p[1] != 0xff ) { data = (unsigned char)~p[1]; p += 2; }\ + else {\ + while ( (p[2] & p[3] & p[4] & p[5]) == 0xff )\ + p += 4, rlen += 32;\ + if ( p[2] != 0xff ) {\ + data = (unsigned char)~p[2]; p += 3; rlen += 8;\ + } else if ( p[3] != 0xff ) {\ + data = (unsigned char)~p[3]; p += 4; rlen += 16;\ + } else if ( p[4] != 0xff ) {\ + data = (unsigned char)~p[4]; p += 5; rlen += 24;\ + } else /* p[5] != 0xff */ {\ + data = (unsigned char)~p[5]; p += 6; rlen += 32;\ + }\ + }\ + }\ + rlen += cf_byte_run_length_0[data ^ 0xff];\ + }\ + count -= rlen;\ +END + +/* Skip over black pixels to find the next white pixel in the input. */ +/* Store the run length in rlen, and update data, p, and count. */ + +#define skip_black_pixels(data, p, count, white_byte, rlen)\ +BEGIN\ + rlen = cf_byte_run_length[count & 7][data];\ + if ( rlen >= 8 ) {\ + if ( white_byte == 0 )\ + for ( ; ; p += 4, rlen += 32 ) {\ + if ( p[0] != 0xff ) { data = p[0]; p += 1; rlen -= 8; break; }\ + if ( p[1] != 0xff ) { data = p[1]; p += 2; break; }\ + if ( p[2] != 0xff ) { data = p[2]; p += 3; rlen += 8; break; }\ + if ( p[3] != 0xff ) { data = p[3]; p += 4; rlen += 16; break; }\ + }\ + else\ + for ( ; ; p += 4, rlen += 32 ) {\ + if ( p[0] ) { data = (unsigned char)~p[0]; p += 1; rlen -= 8; break; }\ + if ( p[1] ) { data = (unsigned char)~p[1]; p += 2; break; }\ + if ( p[2] ) { data = (unsigned char)~p[2]; p += 3; rlen += 8; break; }\ + if ( p[3] ) { data = (unsigned char)~p[3]; p += 4; rlen += 16; break; }\ + }\ + rlen += cf_byte_run_length_0[data];\ + }\ + count -= rlen;\ +END + +#endif /* scf_INCLUDED */ + +/* end of former scf.h */ + +#if USE_BUILTIN_FAXE +#if OBJDEP +# warning PROVIDES: pts_faxe +#endif +/* scfe.c */ +/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */ +/* CCITTFax encoding filter */ +/* #include "config2.h" */ +/* #include "scf.h" */ +/* #include "scfx.h" */ + +/* ------ Macros and support routines ------ */ + +/* Statistics */ + +#ifdef DEBUG + +typedef struct stats_runs_s { + unsigned long termination[64]; + unsigned long make_up[41]; +} stats_runs_t; +static stats_runs_t stats_white_runs, stats_black_runs; + +#define COUNT_RUN(tab, i) (tab)[i]++; + +static void +print_run_stats(const stats_runs_t * stats) +{ + int i; + unsigned long total; + + for (i = 0, total = 0; i < 41; i++) + dprintf1(" %lu", stats->make_up[i]), + total += stats->make_up[i]; + dprintf1(" total=%lu\n\t", total); + for (i = 0, total = 0; i < 64; i++) + dprintf1(" %lu", stats->termination[i]), + total += stats->termination[i]; + dprintf1(" total=%lu\n", total); +} + +#else /* !DEBUG */ + +#define COUNT_RUN(cnt, i) DO_NOTHING + +#endif /* DEBUG */ + +/* Put a run onto the output stream. */ +/* Free variables: q, bits, bits_left. */ + +#define CF_PUT_RUN(ss, lenv, rt, stats)\ +BEGIN\ + cfe_run rr;\ +\ + if ( lenv >= 64 ) {\ + hce_store_state();\ + q = cf_put_long_run(ss, q, lenv, &rt);\ + hce_load_state();\ + lenv &= 63;\ + }\ + rr = rt.termination[lenv];\ + COUNT_RUN(stats.termination, lenv);\ + hc_put_value(ss, q, rr.code, rr.code_length);\ +END + +static unsigned char * +cf_put_long_run(stream_CFE_state * ss, unsigned char * q, int lenv, const cf_runs * prt) +{ + hce_declare_state; + cfe_run rr; + +#ifdef DEBUG + stats_runs_t *pstats = + (prt == &cf_white_runs ? &stats_white_runs : &stats_black_runs); + +#endif + + hce_load_state(); + while (lenv >= 2560 + 64) { + rr = prt->make_up[40]; + COUNT_RUN(pstats->make_up, 40); + hc_put_value(ss, q, rr.code, rr.code_length); + lenv -= 2560; + } + rr = prt->make_up[lenv >> 6]; + COUNT_RUN(pstats->make_up, lenv >> 6); + hc_put_value(ss, q, rr.code, rr.code_length); + hce_store_state(); + return q; +} + +#define CF_PUT_WHITE_RUN(ss, lenv)\ + CF_PUT_RUN(ss, lenv, cf_white_runs, stats_white_runs) + +#define CF_PUT_BLACK_RUN(ss, lenv)\ + CF_PUT_RUN(ss, lenv, cf_black_runs, stats_black_runs) + +/* ------ CCITTFaxEncode ------ */ + +/* private_st_CFE_state(); */ + +static void s_CFE_release _((stream_state *)); + +/* Set default parameter values. */ +static void +s_CFE_set_defaults(register stream_state * st) +{ + stream_CFE_state *const ss = (stream_CFE_state *) st; + + s_CFE_set_defaults_inline(ss); +} + +/* Initialize CCITTFaxEncode filter */ +static int +s_CFE_init(register stream_state * st) +{ + stream_CFE_state *const ss = (stream_CFE_state *) st; + int columns = ss->Columns; + + /* + * The worst case for encoding is alternating white and black pixels. + * For 1-D encoding, the worst case is 9 bits per 2 pixels; for 2-D + * (horizontal), 12 bits per 2 pixels. To fill out a scan line, + * we may add up to 6 12-bit EOL codes. + */ + /**** pts: added UL ****/ + int code_bytes = + ((columns * (ss->K == 0 ? 9UL : 12UL)) >> 4) + 20; /* add slop */ + int raster = ss->raster = + ROUND_UP((columns + 7) >> 3, ss->DecodedByteAlign); + + s_hce_init_inline(ss); + ss->lbuf = ss->lprev = ss->lcode = 0; /* in case we have to release */ + if (columns > cfe_max_width) + return PTSFAX_ERRC; +/****** WRONG ******/ + /* Because skip_white_pixels can look as many as 4 bytes ahead, */ + /* we need to allow 4 extra bytes at the end of the row buffers. */ + ss->lbuf = (unsigned char*)gs_alloc_bytes(st->memory, raster + 4, "CFE lbuf"); + ss->lcode = (unsigned char*)gs_alloc_bytes(st->memory, code_bytes, "CFE lcode"); + if (ss->lbuf == 0 || ss->lcode == 0) { + s_CFE_release(st); + return PTSFAX_ERRC; +/****** WRONG ******/ + } + if (ss->K != 0) { + ss->lprev = (unsigned char*)gs_alloc_bytes(st->memory, raster + 4, "CFE lprev"); + if (ss->lprev == 0) { + s_CFE_release(st); + return PTSFAX_ERRC; +/****** WRONG ******/ + } + /* Clear the initial reference line for 2-D encoding. */ + /* Make sure it is terminated properly. */ + ss->memset_(ss->lprev, (ss->BlackIs1 ? 0 : 0xff), raster); + if (columns & 7) + ss->lprev[raster - 1] ^= 0x80 >> (columns & 7); + else + ss->lprev[raster] = ~ss->lprev[0]; + } + ss->read_count = raster; + ss->write_count = 0; + ss->k_left = (ss->K > 0 ? 1 : ss->K); + ss->max_code_bytes = code_bytes; + return 0; +} + +/* Release the filter. */ +static void +s_CFE_release(stream_state * st) +{ + stream_CFE_state *const ss = (stream_CFE_state *) st; + + gs_free_object(st->memory, ss->lprev, "CFE lprev(close)"); + gs_free_object(st->memory, ss->lcode, "CFE lcode(close)"); + gs_free_object(st->memory, ss->lbuf, "CFE lbuf(close)"); +} + +/* Flush the buffer */ +static void cf_encode_1d _((stream_CFE_state *, const unsigned char *, + stream_cursor_write *)); +static void cf_encode_2d _((stream_CFE_state *, const unsigned char *, + stream_cursor_write *, const unsigned char *)); +static int +s_CFE_process(stream_state * st, stream_cursor_read * pr, + stream_cursor_write * pw, bool last) +{ + stream_CFE_state *const ss = (stream_CFE_state *) st; + const unsigned char *rlimit = pr->limit; + unsigned char *wlimit = pw->limit; + int raster = ss->raster; + unsigned char end_mask = 1 << (-ss->Columns & 7); + int status = 0; + + for (;;) { + stream_cursor_write w; + + if_debug2('w', "[w]CFE: read_count = %d, write_count=%d,\n", + ss->read_count, ss->write_count); + if_debug6('w', " pr = 0x%lx(%d)0x%lx, pw = 0x%lx(%d)0x%lx\n", + (unsigned long) pr->ptr, (int)(rlimit - pr->ptr), (unsigned long) rlimit, + (unsigned long) pw->ptr, (int)(wlimit - pw->ptr), (unsigned long) wlimit); + if (ss->write_count) { + /* Copy more of an encoded line to the caller. */ + int wcount = wlimit - pw->ptr; + int ccount = min(wcount, ss->write_count); + + ss->memcpy_(pw->ptr + 1, ss->lcode + ss->code_bytes - ss->write_count, + ccount); + pw->ptr += ccount; + if ((ss->write_count -= ccount) > 0) { + status = 1; + break; + } + } + if (ss->read_count) { + /* Copy more of an unencoded line from the caller. */ + int rcount = rlimit - pr->ptr; + int ccount = min(rcount, ss->read_count); + + if (rcount == 0 && last) + break; + ss->memcpy_(ss->lbuf + raster - ss->read_count, + pr->ptr + 1, ccount); + pr->ptr += ccount; + if ((ss->read_count -= ccount) != 0) + break; + } + /* + * We have a full scan line in lbuf. Ensure that it ends with + * two polarity changes. + */ + { + unsigned char *end = ss->lbuf + raster - 1; + unsigned char end_bit = *end & end_mask; + unsigned char not_bit = end_bit ^ end_mask; + + *end &= -end_mask; + if (end_mask == 1) + end[1] = (end_bit ? 0x40 : 0x80); + else if (end_mask == 2) + *end |= not_bit >> 1, end[1] = end_bit << 7; + else + *end |= (not_bit >> 1) | (end_bit >> 2); + } + /* + * Write the output directly to the caller's buffer if it's large + * enough, otherwise to our own buffer. + */ + if (wlimit - pw->ptr >= ss->max_code_bytes) { + w = *pw; + } else { + w.ptr = ss->lcode - 1; + w.limit = w.ptr + ss->max_code_bytes; + } +#ifdef DEBUG + if (ss->K > 0) { + if_debug1('w', "[w]new row, k_left=%d\n", + ss->k_left); + } else { + if_debug0('w', "[w]new row\n"); + } +#endif + /* + * Write an EOL (actually a "beginning of line") if requested. + */ + if (ss->EndOfLine) { + const cfe_run *rp = + (ss->K <= 0 ? &cf_run_eol : + ss->k_left > 1 ? &cf2_run_eol_2d : + &cf2_run_eol_1d); + cfe_run run; + + hce_declare_state; + + hce_load_state(); + if (ss->EncodedByteAlign) { + run = *rp; + /* Pad the run on the left */ + /* so it winds up unsigned char-aligned. */ + run.code_length += + (bits_left - run_eol_code_length) & 7; + if (run.code_length > 16) /* <= 23 */ + bits_left -= run.code_length & 7, + run.code_length = 16; + rp = &run; + } + hc_put_code(ss, w.ptr, rp); + hce_store_state(); + } else if (ss->EncodedByteAlign) + ss->bits_left &= ~7; + /* Encode the line. */ + if (ss->K == 0) + cf_encode_1d(ss, ss->lbuf, &w); /* pure 1-D */ + else if (ss->K < 0) + cf_encode_2d(ss, ss->lbuf, &w, ss->lprev); /* pure 2-D */ + else if (--(ss->k_left)) /* mixed, use 2-D */ + cf_encode_2d(ss, ss->lbuf, &w, ss->lprev); + else { /* mixed, use 1-D */ + cf_encode_1d(ss, ss->lbuf, &w); + ss->k_left = ss->K; + } + /* + * If we didn't write directly to the client's buffer, schedule + * the output data to be written. + */ + if (w.limit == wlimit) + pw->ptr = w.ptr; + else + ss->write_count = ss->code_bytes = w.ptr - (ss->lcode - 1); + if (ss->K != 0) { + /* In 2-D modes, swap the current and previous scan lines. */ + unsigned char *temp = ss->lbuf; + + ss->lbuf = ss->lprev; + ss->lprev = temp; + } + /* Note that the input buffer needs refilling. */ + ss->read_count = raster; + } + /* + * When we exit from the loop, we know that write_count = 0, and + * there is no line waiting to be processed in the input buffer. + */ + if (last && status == 0) { + const cfe_run *rp = + (ss->K > 0 ? &cf2_run_eol_1d : &cf_run_eol); + int i = (!ss->EndOfBlock ? 0 : ss->K < 0 ? 2 : 6); + unsigned int bits_to_write = + hc_bits_size - ss->bits_left + i * rp->code_length; + unsigned char *q = pw->ptr; + + hce_declare_state; + + if (0U+(wlimit - q) < (bits_to_write + 7) >> 3) { /* PTS_UNSIGNED */ + status = 1; + goto out; + } + hce_load_state(); + if (ss->EncodedByteAlign) + bits_left &= ~7; + while (--i >= 0) + hc_put_code(ss, q, rp); + /* Force out the last unsigned char or bytes. */ + pw->ptr = hc_put_last_bits((stream_hc_state *) ss, q); + } + out: + if_debug9('w', "[w]CFE exit %d: read_count = %d, write_count = %d,\n pr = 0x%lx(%d)0x%lx; pw = 0x%lx(%d)0x%lx\n", + status, ss->read_count, ss->write_count, + (unsigned long) pr->ptr, (int)(rlimit - pr->ptr), (unsigned long) rlimit, + (unsigned long) pw->ptr, (int)(wlimit - pw->ptr), (unsigned long) wlimit); +#ifdef DEBUG + if (pr->ptr > rlimit || pw->ptr > wlimit) { + lprintf("Pointer overrun!\n"); + status = PTSFAX_ERRC; + } + if (gs_debug_c('w') && status == 1) { + dlputs("[w]white runs:"); + print_run_stats(&stats_white_runs); + dlputs("[w]black runs:"); + print_run_stats(&stats_black_runs); + } +#endif + return status; +} + +/* Encode a 1-D scan line. */ +static void +cf_encode_1d(stream_CFE_state * ss, const unsigned char * lbuf, stream_cursor_write * pw) +{ + unsigned int count = ss->raster << 3; + unsigned char *q = pw->ptr; + int end_count = -ss->Columns & 7; + int rlen; + + hce_declare_state; + const unsigned char *p = lbuf; + unsigned char invert = (ss->BlackIs1 ? 0 : 0xff); + + /* Invariant: data = p[-1] ^ invert. */ + unsigned int data = *p++ ^ invert; + + hce_load_state(); + while (count != 0U+end_count) { /* PTS_UNSIGNED */ + /* Parse a white run. */ + skip_white_pixels(data, p, count, invert, rlen); + CF_PUT_WHITE_RUN(ss, rlen); + if (count == 0U+end_count) /* PTS_UNSIGNED */ + break; + /* Parse a black run. */ + skip_black_pixels(data, p, count, invert, rlen); + CF_PUT_BLACK_RUN(ss, rlen); + } + hce_store_state(); + pw->ptr = q; +} + +/* Encode a 2-D scan line. */ +static void +cf_encode_2d(stream_CFE_state * ss, const unsigned char * lbuf, stream_cursor_write * pw, + const unsigned char * lprev) +{ + unsigned char invert_white = (ss->BlackIs1 ? 0 : 0xff); + unsigned char invert = invert_white; + unsigned int count = ss->raster << 3; + int end_count = -ss->Columns & 7; + const unsigned char *p = lbuf; + unsigned char *q = pw->ptr; + unsigned int data = *p++ ^ invert; + + hce_declare_state; + /* + * In order to handle the nominal 'changing white' at the beginning of + * each scan line, we need to suppress the test for an initial black bit + * in the reference line when we are at the very beginning of the scan + * line. To avoid an extra test, we use two different mask tables. + */ + static const unsigned char initial_count_bit[8] = + { + 0, 1, 2, 4, 8, 0x10, 0x20, 0x40 + }; + static const unsigned char further_count_bit[8] = + { + 0x80, 1, 2, 4, 8, 0x10, 0x20, 0x40 + }; + const unsigned char *count_bit = initial_count_bit; + + hce_load_state(); + while (count != 0U+end_count) { /* PTS_UNSIGNED */ + /* + * If invert == invert_white, white and black have their + * correct meanings; if invert == ~invert_white, + * black and white are interchanged. + */ + unsigned int a0 = count; + unsigned int a1; + +#define b1 (a1 - diff) /* only for printing */ + int diff; + unsigned int prev_count = count; + const unsigned char *prev_p = p - lbuf + lprev; + unsigned char prev_data = prev_p[-1] ^ invert; + int rlen; + + /* Find the a1 and b1 transitions. */ + skip_white_pixels(data, p, count, invert, rlen); + a1 = count; + if ((prev_data & count_bit[prev_count & 7])) { + /* Look for changing white first. */ + skip_black_pixels(prev_data, prev_p, prev_count, invert, rlen); + } + count_bit = further_count_bit; /* no longer at beginning */ + pass: + if (prev_count != 0U+end_count) /* PTS_UNSIGNED */ + skip_white_pixels(prev_data, prev_p, prev_count, invert, rlen); + diff = a1 - prev_count; /* i.e., logical b1 - a1 */ + /* In all the comparisons below, remember that count */ + /* runs downward, not upward, so the comparisons are */ + /* reversed. */ + if (diff <= -2) { + /* Could be a pass mode. Find b2. */ + if (prev_count != 0U+ end_count) /* PTS_UNSIGNED */ + skip_black_pixels(prev_data, prev_p, + prev_count, invert, rlen); + if (prev_count > a1) { + /* Use pass mode. */ + if_debug4('W', "[W]pass: count = %d, a1 = %d, b1 = %d, new count = %d\n", + a0, a1, b1, prev_count); + hc_put_value(ss, q, cf2_run_pass_value, cf2_run_pass_length); + a0 = prev_count; + goto pass; + } + } + /* Check for vertical coding. */ + if (diff <= 3 && diff >= -3) { + /* Use vertical coding. */ + const cfe_run *cp = &cf2_run_vertical[diff + 3]; + + if_debug5('W', "[W]vertical %d: count = %d, a1 = %d, b1 = %d, new count = %d\n", + diff, a0, a1, b1, count); + hc_put_code(ss, q, cp); + invert = ~invert; /* a1 polarity changes */ + data ^= 0xff; + continue; + } + /* No luck, use horizontal coding. */ + if (count != 0U+end_count) /* PTS_UNSIGNED */ + skip_black_pixels(data, p, count, invert, rlen); /* find a2 */ + hc_put_value(ss, q, cf2_run_horizontal_value, + cf2_run_horizontal_length); + a0 -= a1; + a1 -= count; + if (invert == invert_white) { + if_debug3('W', "[W]horizontal: white = %d, black = %d, new count = %d\n", + a0, a1, count); + CF_PUT_WHITE_RUN(ss, a0); + CF_PUT_BLACK_RUN(ss, a1); + } else { + if_debug3('W', "[W]horizontal: black = %d, white = %d, new count = %d\n", + a0, a1, count); + CF_PUT_BLACK_RUN(ss, a0); + CF_PUT_WHITE_RUN(ss, a1); +#undef b1 + } + } + hce_store_state(); + pw->ptr = q; +} + +/* Stream template */ +const stream_template s_CFE_template = { + /*0, &st_CFE_state*/ s_CFE_init, s_CFE_process, 1, 1, + s_CFE_release, s_CFE_set_defaults, 0 +}; +/* end of former scfe.c */ + +/* scfetab.c */ +/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */ +/* Tables for CCITTFaxEncode filter */ +/* #include "scommon.h" */ /* for scf.h */ +/* #include "scf.h" */ + +/* We make this a separate file so that it can be used by */ +/* the program that generates the tables for the CCITTFaxDecode filter. */ + +/* ------ Run encoding tables ------ */ + +/* Abbreviate hce_entry to make the file smaller. */ +#define RUN(c,len) hce_entry(c,len) + +/* Define the end-of-line code. */ +/* Code in scfd.c and scfdgen.c knows that the run value is 1. */ +impl_const cfe_run cf_run_eol = +RUN(run_eol_code_value, run_eol_code_length); + +/* Define the 1-D code that signals uncompressed data. */ +impl_const cfe_run cf1_run_uncompressed = +RUN(0xf, 12); + +/* Define the 2-D run codes. */ +impl_const cfe_run cf2_run_pass = +RUN(cf2_run_pass_value, cf2_run_pass_length); +impl_const cfe_run cf2_run_vertical[7] = +{ + RUN(0x3, 7), + RUN(0x3, 6), + RUN(0x3, 3), + RUN(0x1, 1), + RUN(0x2, 3), + RUN(0x2, 6), + RUN(0x2, 7) +}; +impl_const cfe_run cf2_run_horizontal = +RUN(cf2_run_horizontal_value, cf2_run_horizontal_length); +impl_const cfe_run cf2_run_uncompressed = +RUN(0xf, 10); + +/* EOL codes for Group 3 2-D. */ +/* Code in scfd.c knows that these are 0...01x. */ +impl_const cfe_run cf2_run_eol_1d = +RUN((run_eol_code_value << 1) + 1, run_eol_code_length + 1); +impl_const cfe_run cf2_run_eol_2d = +RUN((run_eol_code_value << 1) + 0, run_eol_code_length + 1); + +/* White run codes. */ +impl_const cf_runs cf_white_runs = +{ + { /* Termination codes */ + RUN(0x35, 8), RUN(0x7, 6), RUN(0x7, 4), RUN(0x8, 4), + RUN(0xb, 4), RUN(0xc, 4), RUN(0xe, 4), RUN(0xf, 4), + RUN(0x13, 5), RUN(0x14, 5), RUN(0x7, 5), RUN(0x8, 5), + RUN(0x8, 6), RUN(0x3, 6), RUN(0x34, 6), RUN(0x35, 6), + RUN(0x2a, 6), RUN(0x2b, 6), RUN(0x27, 7), RUN(0xc, 7), + RUN(0x8, 7), RUN(0x17, 7), RUN(0x3, 7), RUN(0x4, 7), + RUN(0x28, 7), RUN(0x2b, 7), RUN(0x13, 7), RUN(0x24, 7), + RUN(0x18, 7), RUN(0x2, 8), RUN(0x3, 8), RUN(0x1a, 8), + RUN(0x1b, 8), RUN(0x12, 8), RUN(0x13, 8), RUN(0x14, 8), + RUN(0x15, 8), RUN(0x16, 8), RUN(0x17, 8), RUN(0x28, 8), + RUN(0x29, 8), RUN(0x2a, 8), RUN(0x2b, 8), RUN(0x2c, 8), + RUN(0x2d, 8), RUN(0x4, 8), RUN(0x5, 8), RUN(0xa, 8), + RUN(0xb, 8), RUN(0x52, 8), RUN(0x53, 8), RUN(0x54, 8), + RUN(0x55, 8), RUN(0x24, 8), RUN(0x25, 8), RUN(0x58, 8), + RUN(0x59, 8), RUN(0x5a, 8), RUN(0x5b, 8), RUN(0x4a, 8), + RUN(0x4b, 8), RUN(0x32, 8), RUN(0x33, 8), RUN(0x34, 8) + }, + { /* Make-up codes */ + RUN(0, 0) /* dummy */ , RUN(0x1b, 5), RUN(0x12, 5), RUN(0x17, 6), + RUN(0x37, 7), RUN(0x36, 8), RUN(0x37, 8), RUN(0x64, 8), + RUN(0x65, 8), RUN(0x68, 8), RUN(0x67, 8), RUN(0xcc, 9), + RUN(0xcd, 9), RUN(0xd2, 9), RUN(0xd3, 9), RUN(0xd4, 9), + RUN(0xd5, 9), RUN(0xd6, 9), RUN(0xd7, 9), RUN(0xd8, 9), + RUN(0xd9, 9), RUN(0xda, 9), RUN(0xdb, 9), RUN(0x98, 9), + RUN(0x99, 9), RUN(0x9a, 9), RUN(0x18, 6), RUN(0x9b, 9), + RUN(0x8, 11), RUN(0xc, 11), RUN(0xd, 11), RUN(0x12, 12), + RUN(0x13, 12), RUN(0x14, 12), RUN(0x15, 12), RUN(0x16, 12), + RUN(0x17, 12), RUN(0x1c, 12), RUN(0x1d, 12), RUN(0x1e, 12), + RUN(0x1f, 12) + } +}; + +/* Black run codes. */ +impl_const cf_runs cf_black_runs = +{ + { /* Termination codes */ + RUN(0x37, 10), RUN(0x2, 3), RUN(0x3, 2), RUN(0x2, 2), + RUN(0x3, 3), RUN(0x3, 4), RUN(0x2, 4), RUN(0x3, 5), + RUN(0x5, 6), RUN(0x4, 6), RUN(0x4, 7), RUN(0x5, 7), + RUN(0x7, 7), RUN(0x4, 8), RUN(0x7, 8), RUN(0x18, 9), + RUN(0x17, 10), RUN(0x18, 10), RUN(0x8, 10), RUN(0x67, 11), + RUN(0x68, 11), RUN(0x6c, 11), RUN(0x37, 11), RUN(0x28, 11), + RUN(0x17, 11), RUN(0x18, 11), RUN(0xca, 12), RUN(0xcb, 12), + RUN(0xcc, 12), RUN(0xcd, 12), RUN(0x68, 12), RUN(0x69, 12), + RUN(0x6a, 12), RUN(0x6b, 12), RUN(0xd2, 12), RUN(0xd3, 12), + RUN(0xd4, 12), RUN(0xd5, 12), RUN(0xd6, 12), RUN(0xd7, 12), + RUN(0x6c, 12), RUN(0x6d, 12), RUN(0xda, 12), RUN(0xdb, 12), + RUN(0x54, 12), RUN(0x55, 12), RUN(0x56, 12), RUN(0x57, 12), + RUN(0x64, 12), RUN(0x65, 12), RUN(0x52, 12), RUN(0x53, 12), + RUN(0x24, 12), RUN(0x37, 12), RUN(0x38, 12), RUN(0x27, 12), + RUN(0x28, 12), RUN(0x58, 12), RUN(0x59, 12), RUN(0x2b, 12), + RUN(0x2c, 12), RUN(0x5a, 12), RUN(0x66, 12), RUN(0x67, 12) + }, + { /* Make-up codes. */ + RUN(0, 0) /* dummy */ , RUN(0xf, 10), RUN(0xc8, 12), RUN(0xc9, 12), + RUN(0x5b, 12), RUN(0x33, 12), RUN(0x34, 12), RUN(0x35, 12), + RUN(0x6c, 13), RUN(0x6d, 13), RUN(0x4a, 13), RUN(0x4b, 13), + RUN(0x4c, 13), RUN(0x4d, 13), RUN(0x72, 13), RUN(0x73, 13), + RUN(0x74, 13), RUN(0x75, 13), RUN(0x76, 13), RUN(0x77, 13), + RUN(0x52, 13), RUN(0x53, 13), RUN(0x54, 13), RUN(0x55, 13), + RUN(0x5a, 13), RUN(0x5b, 13), RUN(0x64, 13), RUN(0x65, 13), + RUN(0x8, 11), RUN(0xc, 11), RUN(0xd, 11), RUN(0x12, 12), + RUN(0x13, 12), RUN(0x14, 12), RUN(0x15, 12), RUN(0x16, 12), + RUN(0x17, 12), RUN(0x1c, 12), RUN(0x1d, 12), RUN(0x1e, 12), + RUN(0x1f, 12) + } +}; + +/* Uncompressed codes. */ +impl_const cfe_run cf_uncompressed[6] = +{ + RUN(1, 1), + RUN(1, 2), + RUN(1, 3), + RUN(1, 4), + RUN(1, 5), + RUN(1, 6) +}; + +/* Uncompressed exit codes. */ +impl_const cfe_run cf_uncompressed_exit[10] = +{ + RUN(2, 8), RUN(3, 8), + RUN(2, 9), RUN(3, 9), + RUN(2, 10), RUN(3, 10), + RUN(2, 11), RUN(3, 11), + RUN(2, 12), RUN(3, 12) +}; + +#if 0 +/* Some C compilers insist on having executable code in every file.... */ +void scfetab_dummy _((void)); /* for picky compilers */ +void +scfetab_dummy(void) +{ +} +#endif + +/* end of former scfetab.c */ + +#endif /* USE_BUILTIN_FAXE */ + +#if USE_BUILTIN_FAXD +#if OBJDEP +# warning PROVIDES: pts_faxd +#endif +/* scfdtab.c; must be before scfd.c */ +/* #include "scommon.h" */ /* for scf.h */ +/* #include "scf.h" */ + +/* White decoding table. */ +impl_const cfd_node cf_white_decode[] = { + { 256, 12 }, + { 272, 12 }, + { 29, 8 }, + { 30, 8 }, + { 45, 8 }, + { 46, 8 }, + { 22, 7 }, + { 22, 7 }, + { 23, 7 }, + { 23, 7 }, + { 47, 8 }, + { 48, 8 }, + { 13, 6 }, + { 13, 6 }, + { 13, 6 }, + { 13, 6 }, + { 20, 7 }, + { 20, 7 }, + { 33, 8 }, + { 34, 8 }, + { 35, 8 }, + { 36, 8 }, + { 37, 8 }, + { 38, 8 }, + { 19, 7 }, + { 19, 7 }, + { 31, 8 }, + { 32, 8 }, + { 1, 6 }, + { 1, 6 }, + { 1, 6 }, + { 1, 6 }, + { 12, 6 }, + { 12, 6 }, + { 12, 6 }, + { 12, 6 }, + { 53, 8 }, + { 54, 8 }, + { 26, 7 }, + { 26, 7 }, + { 39, 8 }, + { 40, 8 }, + { 41, 8 }, + { 42, 8 }, + { 43, 8 }, + { 44, 8 }, + { 21, 7 }, + { 21, 7 }, + { 28, 7 }, + { 28, 7 }, + { 61, 8 }, + { 62, 8 }, + { 63, 8 }, + { 0, 8 }, + { 320, 8 }, + { 384, 8 }, + { 10, 5 }, + { 10, 5 }, + { 10, 5 }, + { 10, 5 }, + { 10, 5 }, + { 10, 5 }, + { 10, 5 }, + { 10, 5 }, + { 11, 5 }, + { 11, 5 }, + { 11, 5 }, + { 11, 5 }, + { 11, 5 }, + { 11, 5 }, + { 11, 5 }, + { 11, 5 }, + { 27, 7 }, + { 27, 7 }, + { 59, 8 }, + { 60, 8 }, + { 288, 9 }, + { 290, 9 }, + { 18, 7 }, + { 18, 7 }, + { 24, 7 }, + { 24, 7 }, + { 49, 8 }, + { 50, 8 }, + { 51, 8 }, + { 52, 8 }, + { 25, 7 }, + { 25, 7 }, + { 55, 8 }, + { 56, 8 }, + { 57, 8 }, + { 58, 8 }, + { 192, 6 }, + { 192, 6 }, + { 192, 6 }, + { 192, 6 }, + { 1664, 6 }, + { 1664, 6 }, + { 1664, 6 }, + { 1664, 6 }, + { 448, 8 }, + { 512, 8 }, + { 292, 9 }, + { 640, 8 }, + { 576, 8 }, + { 294, 9 }, + { 296, 9 }, + { 298, 9 }, + { 300, 9 }, + { 302, 9 }, + { 256, 7 }, + { 256, 7 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 128, 5 }, + { 128, 5 }, + { 128, 5 }, + { 128, 5 }, + { 128, 5 }, + { 128, 5 }, + { 128, 5 }, + { 128, 5 }, + { 8, 5 }, + { 8, 5 }, + { 8, 5 }, + { 8, 5 }, + { 8, 5 }, + { 8, 5 }, + { 8, 5 }, + { 8, 5 }, + { 9, 5 }, + { 9, 5 }, + { 9, 5 }, + { 9, 5 }, + { 9, 5 }, + { 9, 5 }, + { 9, 5 }, + { 9, 5 }, + { 16, 6 }, + { 16, 6 }, + { 16, 6 }, + { 16, 6 }, + { 17, 6 }, + { 17, 6 }, + { 17, 6 }, + { 17, 6 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 14, 6 }, + { 14, 6 }, + { 14, 6 }, + { 14, 6 }, + { 15, 6 }, + { 15, 6 }, + { 15, 6 }, + { 15, 6 }, + { 64, 5 }, + { 64, 5 }, + { 64, 5 }, + { 64, 5 }, + { 64, 5 }, + { 64, 5 }, + { 64, 5 }, + { 64, 5 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { -2, 3 }, + { -2, 3 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -3, 4 }, + { 1792, 3 }, + { 1792, 3 }, + { 1984, 4 }, + { 2048, 4 }, + { 2112, 4 }, + { 2176, 4 }, + { 2240, 4 }, + { 2304, 4 }, + { 1856, 3 }, + { 1856, 3 }, + { 1920, 3 }, + { 1920, 3 }, + { 2368, 4 }, + { 2432, 4 }, + { 2496, 4 }, + { 2560, 4 }, + { 1472, 1 }, + { 1536, 1 }, + { 1600, 1 }, + { 1728, 1 }, + { 704, 1 }, + { 768, 1 }, + { 832, 1 }, + { 896, 1 }, + { 960, 1 }, + { 1024, 1 }, + { 1088, 1 }, + { 1152, 1 }, + { 1216, 1 }, + { 1280, 1 }, + { 1344, 1 }, + { 1408, 1 } +}; + +/* Black decoding table. */ +impl_const cfd_node cf_black_decode[] = { + { 128, 12 }, + { 160, 13 }, + { 224, 12 }, + { 256, 12 }, + { 10, 7 }, + { 11, 7 }, + { 288, 12 }, + { 12, 7 }, + { 9, 6 }, + { 9, 6 }, + { 8, 6 }, + { 8, 6 }, + { 7, 5 }, + { 7, 5 }, + { 7, 5 }, + { 7, 5 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { -2, 4 }, + { -2, 4 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -3, 5 }, + { 1792, 4 }, + { 1792, 4 }, + { 1984, 5 }, + { 2048, 5 }, + { 2112, 5 }, + { 2176, 5 }, + { 2240, 5 }, + { 2304, 5 }, + { 1856, 4 }, + { 1856, 4 }, + { 1920, 4 }, + { 1920, 4 }, + { 2368, 5 }, + { 2432, 5 }, + { 2496, 5 }, + { 2560, 5 }, + { 18, 3 }, + { 18, 3 }, + { 18, 3 }, + { 18, 3 }, + { 18, 3 }, + { 18, 3 }, + { 18, 3 }, + { 18, 3 }, + { 52, 5 }, + { 52, 5 }, + { 640, 6 }, + { 704, 6 }, + { 768, 6 }, + { 832, 6 }, + { 55, 5 }, + { 55, 5 }, + { 56, 5 }, + { 56, 5 }, + { 1280, 6 }, + { 1344, 6 }, + { 1408, 6 }, + { 1472, 6 }, + { 59, 5 }, + { 59, 5 }, + { 60, 5 }, + { 60, 5 }, + { 1536, 6 }, + { 1600, 6 }, + { 24, 4 }, + { 24, 4 }, + { 24, 4 }, + { 24, 4 }, + { 25, 4 }, + { 25, 4 }, + { 25, 4 }, + { 25, 4 }, + { 1664, 6 }, + { 1728, 6 }, + { 320, 5 }, + { 320, 5 }, + { 384, 5 }, + { 384, 5 }, + { 448, 5 }, + { 448, 5 }, + { 512, 6 }, + { 576, 6 }, + { 53, 5 }, + { 53, 5 }, + { 54, 5 }, + { 54, 5 }, + { 896, 6 }, + { 960, 6 }, + { 1024, 6 }, + { 1088, 6 }, + { 1152, 6 }, + { 1216, 6 }, + { 64, 3 }, + { 64, 3 }, + { 64, 3 }, + { 64, 3 }, + { 64, 3 }, + { 64, 3 }, + { 64, 3 }, + { 64, 3 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 23, 4 }, + { 23, 4 }, + { 50, 5 }, + { 51, 5 }, + { 44, 5 }, + { 45, 5 }, + { 46, 5 }, + { 47, 5 }, + { 57, 5 }, + { 58, 5 }, + { 61, 5 }, + { 256, 5 }, + { 16, 3 }, + { 16, 3 }, + { 16, 3 }, + { 16, 3 }, + { 17, 3 }, + { 17, 3 }, + { 17, 3 }, + { 17, 3 }, + { 48, 5 }, + { 49, 5 }, + { 62, 5 }, + { 63, 5 }, + { 30, 5 }, + { 31, 5 }, + { 32, 5 }, + { 33, 5 }, + { 40, 5 }, + { 41, 5 }, + { 22, 4 }, + { 22, 4 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 15, 2 }, + { 15, 2 }, + { 15, 2 }, + { 15, 2 }, + { 15, 2 }, + { 15, 2 }, + { 15, 2 }, + { 15, 2 }, + { 128, 5 }, + { 192, 5 }, + { 26, 5 }, + { 27, 5 }, + { 28, 5 }, + { 29, 5 }, + { 19, 4 }, + { 19, 4 }, + { 20, 4 }, + { 20, 4 }, + { 34, 5 }, + { 35, 5 }, + { 36, 5 }, + { 37, 5 }, + { 38, 5 }, + { 39, 5 }, + { 21, 4 }, + { 21, 4 }, + { 42, 5 }, + { 43, 5 }, + { 0, 3 }, + { 0, 3 }, + { 0, 3 }, + { 0, 3 } +}; + +/* 2-D decoding table. */ +impl_const cfd_node cf_2d_decode[] = { + { 128, 11 }, + { 144, 10 }, + { 6, 7 }, + { 0, 7 }, + { 5, 6 }, + { 5, 6 }, + { 1, 6 }, + { 1, 6 }, + { -4, 4 }, + { -4, 4 }, + { -4, 4 }, + { -4, 4 }, + { -4, 4 }, + { -4, 4 }, + { -4, 4 }, + { -4, 4 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { -2, 4 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -3, 3 } +}; + +/* Uncompresssed decoding table. */ +impl_const cfd_node cf_uncompressed_decode[] = { + { 64, 12 }, + { 5, 6 }, + { 4, 5 }, + { 4, 5 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { -1, 0 }, + { -1, 0 }, + { 8, 6 }, + { 9, 6 }, + { 6, 5 }, + { 6, 5 }, + { 7, 5 }, + { 7, 5 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 3, 3 }, + { 3, 3 }, + { 3, 3 }, + { 3, 3 }, + { 3, 3 }, + { 3, 3 }, + { 3, 3 }, + { 3, 3 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 } +}; + +#if 0 +/* Dummy executable code to pacify compilers. */ +void scfdtab_dummy _((void)); +void +scfdtab_dummy() +{ +} +#endif +/* end of former scfdtab.c */ +/* scfd.c */ +/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */ +/* CCITTFax decoding filter */ +/* #include "gstypes.h" */ +/* #include "scf.h" */ +/* #include "scfx.h" */ + +/* Utility procedures */ +int stream_move _((stream_cursor_read *, stream_cursor_write *)); /* in stream.c */ + +/* ------ CCITTFaxDecode ------ */ + +/* private_st_CFD_state(); */ + +/* Set default parameter values. */ +static void +s_CFD_set_defaults(register stream_state * st) +{ + stream_CFD_state *const ss = (stream_CFD_state *) st; + + s_CFD_set_defaults_inline(ss); +} + +/* Initialize CCITTFaxDecode filter */ +static int +s_CFD_init(stream_state * st) +{ + stream_CFD_state *const ss = (stream_CFD_state *) st; + int raster = ss->raster = + ROUND_UP((ss->Columns + 7) >> 3, ss->DecodedByteAlign); + unsigned char white = (ss->BlackIs1 ? 0 : 0xff); + + s_hcd_init_inline(ss); + /* Because skip_white_pixels can look as many as 4 bytes ahead, */ + /* we need to allow 4 extra bytes at the end of the row buffers. */ + ss->lbuf = (unsigned char*)gs_alloc_bytes(st->memory, raster + 4, "CFD lbuf"); + ss->lprev = 0; + if (ss->lbuf == 0) + return PTSFAX_ERRC; +/****** WRONG ******/ + if (ss->K != 0) { + ss->lprev = (unsigned char*)gs_alloc_bytes(st->memory, raster + 4, "CFD lprev"); + if (ss->lprev == 0) + return PTSFAX_ERRC; +/****** WRONG ******/ + /* Clear the initial reference line for 2-D encoding. */ + ss->memset_(ss->lbuf, white, raster); + /* Ensure that the scan of the reference line will stop. */ + ss->lbuf[raster] = 0xa0; + } + ss->k_left = min(ss->K, 0); + ss->run_color = 0; + ss->damaged_rows = 0; + ss->skipping_damage = false; + ss->cbit = 0; + ss->uncomp_run = 0; + ss->rows_left = (ss->Rows <= 0 || ss->EndOfBlock ? -1 : ss->Rows + 1); + ss->rpos = ss->wpos = raster - 1; + ss->eol_count = 0; + ss->invert = white; + ss->min_left = 1; + return 0; +} + +/* Release the filter. */ +static void +s_CFD_release(stream_state * st) +{ + stream_CFD_state *const ss = (stream_CFD_state *) st; + + gs_free_object(st->memory, ss->lprev, "CFD lprev(close)"); + gs_free_object(st->memory, ss->lbuf, "CFD lbuf(close)"); +} + +/* Declare the variables that hold the state. */ +#define cfd_declare_state\ + hcd_declare_state;\ + register unsigned char *q;\ + int qbit +/* Load the state from the stream. */ +#define cfd_load_state()\ + hcd_load_state(),\ + q = ss->lbuf + ss->wpos, qbit = ss->cbit +/* Store the state back in the stream. */ +#define cfd_store_state()\ + hcd_store_state(),\ + ss->wpos = q - ss->lbuf, ss->cbit = qbit + +/* Macros to get blocks of bits from the input stream. */ +/* Invariants: 0 <= bits_left <= bits_size; */ +/* bits [bits_left-1..0] contain valid data. */ + +#define avail_bits(n) hcd_bits_available(n) +#define ensure_bits(n, outl) hcd_ensure_bits(n, outl) +#define peek_bits(n) hcd_peek_bits(n) +#define peek_var_bits(n) hcd_peek_var_bits(n) +#define skip_bits(n) hcd_skip_bits(n) + +/* Get a run from the stream. */ +#ifdef DEBUG +# define IF_DEBUG(expr) expr +#else +# define IF_DEBUG(expr) DO_NOTHING +#endif +#define get_run(decode, initial_bits, min_bits, runlen, str, locl, outl)\ + BEGIN\ + const cfd_node *np;\ + int clen;\ +\ + HCD_ENSURE_BITS_ELSE(initial_bits) {\ + /* We might still have enough bits for the specific code. */\ + if (bits_left < min_bits) goto outl;\ + np = &decode[hcd_peek_bits_left() << (initial_bits - bits_left)];\ + if ((clen = np->code_length) > bits_left) goto outl;\ + goto locl;\ + }\ + np = &decode[peek_bits(initial_bits)];\ + if ((clen = np->code_length) > initial_bits) {\ + IF_DEBUG(unsigned int init_bits = peek_bits(initial_bits));\ + if (!avail_bits(clen)) goto outl;\ + clen -= initial_bits;\ + skip_bits(initial_bits);\ + ensure_bits(clen, outl); /* can't goto outl */\ + np = &decode[np->run_length + peek_var_bits(clen)];\ + if_debug4('W', "%s xcode=0x%x,%d rlen=%d\n", str,\ + (init_bits << np->code_length) +\ + peek_var_bits(np->code_length),\ + initial_bits + np->code_length,\ + np->run_length);\ + skip_bits(np->code_length);\ + } else {\ + locl: if_debug4('W', "%s code=0x%x,%d rlen=%d\n", str,\ + peek_var_bits(clen), clen, np->run_length);\ + skip_bits(clen);\ + }\ + runlen = np->run_length;\ + END + +/* Skip data bits for a white run. */ +/* rlen is either less than 64, or a multiple of 64. */ +#define skip_data(rlen, makeup_label)\ + if ( (qbit -= rlen) < 0 )\ + { q -= qbit >> 3, qbit &= 7;\ + if ( rlen >= 64 ) goto makeup_label;\ + } + +/* Invert data bits for a black run. */ +/* If rlen >= 64, execute makeup_action: this is to handle */ +/* makeup codes efficiently, since these are always a multiple of 64. */ +#define invert_data(rlen, black_byte, makeup_action, d)\ + if ( rlen > qbit )\ + { *q++ ^= (1 << qbit) - 1;\ + rlen -= qbit;\ + switch ( rlen >> 3 )\ + {\ + case 7: /* original rlen possibly >= 64 */\ + if ( rlen + qbit >= 64 ) goto d;\ + *q++ = black_byte;\ + case 6: *q++ = black_byte;\ + case 5: *q++ = black_byte;\ + case 4: *q++ = black_byte;\ + case 3: *q++ = black_byte;\ + case 2: *q++ = black_byte;\ + case 1: *q = black_byte;\ + rlen &= 7;\ + if ( !rlen ) { qbit = 0; break; }\ + q++;\ + case 0: /* know rlen != 0 */\ + qbit = 8 - rlen;\ + *q ^= 0xff << qbit;\ + break;\ + default: /* original rlen >= 64 */\ +d: ss->memset_(q, black_byte, rlen >> 3);\ + q += rlen >> 3;\ + rlen &= 7;\ + if ( !rlen ) qbit = 0, q--;\ + else qbit = 8 - rlen, *q ^= 0xff << qbit;\ + makeup_action;\ + }\ + }\ + else\ + qbit -= rlen,\ + *q ^= ((1 << rlen) - 1) << qbit + +/* Buffer refill for CCITTFaxDecode filter */ +static int cf_decode_eol _((stream_CFD_state *, stream_cursor_read *)); +static int cf_decode_1d _((stream_CFD_state *, stream_cursor_read *)); +static int cf_decode_2d _((stream_CFD_state *, stream_cursor_read *)); +static int cf_decode_uncompressed _((stream_CFD_state *, stream_cursor_read *)); +static int +s_CFD_process(stream_state * st, stream_cursor_read * pr, + stream_cursor_write * pw, bool last) +{ + stream_CFD_state *const ss = (stream_CFD_state *) st; + int wstop = ss->raster - 1; + int eol_count = ss->eol_count; + int k_left = ss->k_left; + int rows_left = ss->rows_left; + int status = 0; + + (void)last; /**** pts ****/ + +#ifdef DEBUG + const unsigned char *rstart = pr->ptr; + const unsigned char *wstart = pw->ptr; + +#endif + + top: +#ifdef DEBUG + { + hcd_declare_state; + hcd_load_state(); + if_debug8('w', "\ +[w]CFD_process top: eol_count=%d, k_left=%d, rows_left=%d\n\ + bits=0x%lx, bits_left=%d, read %u, wrote %u%s\n", + eol_count, k_left, rows_left, + (unsigned long) bits, bits_left, + (unsigned int) (p - rstart), (unsigned int) (pw->ptr - wstart), + (ss->skipping_damage ? ", skipping damage" : "")); + } +#endif + if (ss->skipping_damage) { /* Skip until we reach an EOL. */ + hcd_declare_state; + int skip; + + status = 0; + do { + switch ((skip = cf_decode_eol(ss, pr))) { + default: /* not EOL */ + hcd_load_state(); + skip_bits(-skip); + hcd_store_state(); + continue; + case 0: /* need more input */ + goto out; + case 1: /* EOL */ + { /* Back up over the EOL. */ + hcd_load_state(); + bits_left += run_eol_code_length; + hcd_store_state(); + } + ss->skipping_damage = false; + } + } + while (ss->skipping_damage); + ss->damaged_rows++; + } + /* + * Check for a completed input scan line. This isn't quite as + * simple as it seems, because we could have run out of input data + * between a makeup code and a 0-length termination code, or in a + * 2-D line before a final horizontal code with a 0-length second + * run. There's probably a way to think about this situation that + * doesn't require a special check, but I haven't found it yet. + */ + if (ss->wpos == wstop && ss->cbit <= (-ss->Columns & 7) && + (k_left == 0 ? !(ss->run_color & ~1) : ss->run_color == 0) + ) { /* Check for completed data to be copied to the client. */ + /* (We could avoid the extra copy step for 1-D, but */ + /* it's simpler not to, and it doesn't cost much.) */ + if (ss->rpos < ss->wpos) { + stream_cursor_read cr; + + cr.ptr = ss->lbuf + ss->rpos; + cr.limit = ss->lbuf + ss->wpos; + status = stream_move(&cr, pw); + ss->rpos = cr.ptr - ss->lbuf; + if (status) + goto out; + } + if (rows_left > 0 && --rows_left == 0) { + status = EOFC; + goto out; + } + if (ss->K != 0) { + unsigned char *prev_bits = ss->lprev; + + ss->lprev = ss->lbuf; + ss->lbuf = prev_bits; + if (ss->K > 0) + k_left = (k_left == 0 ? ss->K : k_left) - 1; + } + ss->rpos = ss->wpos = -1; + ss->eol_count = eol_count = 0; + ss->cbit = 0; + ss->invert = (ss->BlackIs1 ? 0 : 0xff); + ss->memset_(ss->lbuf, ss->invert, wstop + 1); + ss->run_color = 0; + /* + * If EndOfLine is true, we want to include the unsigned char padding + * in the string of initial zeros in the EOL. If EndOfLine + * is false, we aren't sure what we should do.... + */ + if (ss->EncodedByteAlign & !ss->EndOfLine) + ss->bits_left &= ~7; + } + /* If we're between scan lines, scan for EOLs. */ + if (ss->wpos < 0) { + while ((status = cf_decode_eol(ss, pr)) > 0) { + if_debug0('w', "[w]EOL\n"); + /* If we are in a Group 3 mixed regime, */ + /* check the next bit for 1- vs. 2-D. */ + if (ss->K > 0) { + hcd_declare_state; + hcd_load_state(); + ensure_bits(1, out); /* can't fail */ + k_left = (peek_bits(1) ? 0 : 1); + skip_bits(1); + hcd_store_state(); + } + ++eol_count; + /* + * According to Adobe, the decoder should always check for + * the EOD sequence, regardless of EndOfBlock: the Red Book's + * documentation of EndOfBlock is wrong. + */ + if (eol_count == (ss->K < 0 ? 2 : 6)) { + status = EOFC; + goto out; + } + } + if (status == 0) /* input empty while scanning EOLs */ + goto out; + switch (eol_count) { + case 0: + if (ss->EndOfLine) { /* EOL is required, but none is present. */ + status = PTSFAX_ERRC; + goto check; + } + case 1: + break; + default: + status = PTSFAX_ERRC; + goto check; + } + } + /* Now decode actual data. */ + if (k_left < 0) { + if_debug0('w', "[w2]new row\n"); + status = cf_decode_2d(ss, pr); + } else if (k_left == 0) { + if_debug0('w', "[w1]new row\n"); + status = cf_decode_1d(ss, pr); + } else { + if_debug1('w', "[w1]new 2-D row, %d left\n", k_left); + status = cf_decode_2d(ss, pr); + } + if_debug3('w', "[w]CFD status = %d, wpos = %d, cbit = %d\n", + status, ss->wpos, ss->cbit); + check:switch (status) { + case 1: /* output full */ + goto top; + case PTSFAX_ERRC: + /* Check for special handling of damaged rows. */ + if (ss->damaged_rows >= ss->DamagedRowsBeforeError || + !(ss->EndOfLine && ss->K >= 0) + ) + break; + /* Substitute undamaged data if appropriate. */ +/****** NOT IMPLEMENTED YET ******/ + { + ss->wpos = wstop; + ss->cbit = -ss->Columns & 7; + ss->run_color = 0; + } + ss->skipping_damage = true; + goto top; + default: + ss->damaged_rows = 0; /* finished a good row */ + } + out:ss->k_left = k_left; + ss->rows_left = rows_left; + ss->eol_count = eol_count; + return status; +} + +/* + * Decode a leading EOL, if any. + * If an EOL is present, skip over it and return 1; + * if no EOL is present, read no input and return -N, where N is the + * number of initial bits that can be skipped in the search for an EOL; + * if more input is needed, return 0. + * Note that if we detected an EOL, we know that we can back up over it; + * if we detected an N-bit non-EOL, we know that at least N bits of data + * are available in the buffer. + */ +static int +cf_decode_eol(stream_CFD_state * ss, stream_cursor_read * pr) +{ + hcd_declare_state; + int zeros; + int look_ahead; + + hcd_load_state(); + for (zeros = 0; zeros < run_eol_code_length - 1; zeros++) { + ensure_bits(1, out); + if (peek_bits(1)) + return -(zeros + 1); + skip_bits(1); + } + /* We definitely have an EOL. Skip further zero bits. */ + look_ahead = (ss->K > 0 ? 2 : 1); + for (;;) { + ensure_bits(look_ahead, back); + if (peek_bits(1)) + break; + skip_bits(1); + } + skip_bits(1); + hcd_store_state(); + return 1; + back: /* + * We ran out of data while skipping zeros. + * We know we are at a unsigned char boundary, and have just skipped + * at least run_eol_code_length - 1 zeros. However, + * bits_left may be 1 if look_ahead == 2. + */ + bits &= (1 << bits_left) - 1; + bits_left += run_eol_code_length - 1; + hcd_store_state(); + out:return 0; +} + +/* Decode a 1-D scan line. */ +static int +cf_decode_1d(stream_CFD_state * ss, stream_cursor_read * pr) +{ + cfd_declare_state; + unsigned char black_byte = (ss->BlackIs1 ? 0xff : 0); + int end_bit = -ss->Columns & 7; + unsigned char *stop = ss->lbuf - 1 + ss->raster; + int run_color = ss->run_color; + int status; + int bcnt; + + cfd_load_state(); + if_debug1('w', "[w1]entry run_color = %d\n", ss->run_color); + if (ss->run_color > 0) + goto db; + else + goto dw; +#define q_at_stop() (q >= stop && (qbit <= end_bit || q > stop)) + top:run_color = 0; + if (q_at_stop()) + goto done; + dw: /* Decode a white run. */ + get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits, + bcnt, "[w1]white", dwl, out0); + if (bcnt < 0) { /* exceptional situation */ + switch (bcnt) { + case run_uncompressed: /* Uncompressed data. */ + cfd_store_state(); + bcnt = cf_decode_uncompressed(ss, pr); + if (bcnt < 0) + return bcnt; + cfd_load_state(); + if (bcnt) + goto db; + else + goto dw; + /*case run_error: */ + /*case run_zeros: *//* Premature end-of-line. */ + default: + status = PTSFAX_ERRC; + goto out; + } + } + skip_data(bcnt, dwx); + if (q_at_stop()) { + run_color = 0; /* not inside a run */ + goto done; + } + run_color = 1; + db: /* Decode a black run. */ + get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits, + bcnt, "[w1]black", dbl, out1); + if (bcnt < 0) { /* All exceptional codes are invalid here. */ +/****** WRONG, uncompressed IS ALLOWED ******/ + status = PTSFAX_ERRC; + goto out; + } + /* Invert bits designated by black run. */ + invert_data(bcnt, black_byte, goto dbx, idb); + goto top; + dwx: /* If we run out of data after a makeup code, */ + /* note that we are still processing a white run. */ + run_color = -1; + goto dw; + dbx: /* If we run out of data after a makeup code, */ + /* note that we are still processing a black run. */ + run_color = 2; + goto db; + done:if (q > stop || qbit < end_bit) + status = PTSFAX_ERRC; + else + status = 1; + out:cfd_store_state(); + ss->run_color = run_color; + if_debug1('w', "[w1]exit run_color = %d\n", run_color); + return status; + out0: /* We already set run_color to 0 or -1. */ + status = 0; + goto out; + out1: /* We already set run_color to 1 or 2. */ + status = 0; + goto out; +} + +/* Decode a 2-D scan line. */ +static int +cf_decode_2d(stream_CFD_state * ss, stream_cursor_read * pr) +{ + cfd_declare_state; + unsigned char invert_white = (ss->BlackIs1 ? 0 : 0xff); + unsigned char black_byte = ~invert_white; + unsigned char invert = ss->invert; + int end_count = -ss->Columns & 7; + unsigned int raster = ss->raster; + unsigned char *q0 = ss->lbuf; + unsigned char *prev_q01 = ss->lprev + 1; + unsigned char *endptr = q0 - 1 + raster; + int init_count = raster << 3; + register int count; + int rlen; + int status; + + cfd_load_state(); + count = ((endptr - q) << 3) + qbit; + endptr[1] = 0xa0; /* a unsigned char with some 0s and some 1s, */ + /* to ensure run scan will stop */ + if_debug1('W', "[w2]raster=%d\n", raster); + switch (ss->run_color) { + case -2: + ss->run_color = 0; + goto hww; + case -1: + ss->run_color = 0; + goto hbw; + case 1: + ss->run_color = 0; + goto hwb; + case 2: + ss->run_color = 0; + goto hbb; + /*case 0: */ + } + top:if (count <= end_count) { + status = (count < end_count ? PTSFAX_ERRC : 1); + goto out; + } + /* If invert == invert_white, white and black have their */ + /* correct meanings; if invert == ~invert_white, */ + /* black and white are interchanged. */ + if_debug1('W', "[w2]%4d:\n", count); +#ifdef DEBUG + /* Check the invariant between q, qbit, and count. */ + { + int pcount = (endptr - q) * 8 + qbit; + + if (pcount != count) + dlprintf2("[w2]Error: count=%d pcount=%d\n", + count, pcount); + } +#endif + /* + * We could just use get_run here, but we can do better. However, + * we must be careful to handle the case where the very last codes + * in the input stream are 1-bit "vertical 0" codes: we can't just + * use ensure_bits(3, ...) and go to get more data if it fails. + */ + ensure_bits(3, out3); +#define vertical_0 (countof(cf2_run_vertical) / 2) + switch (peek_bits(3)) { + default /*4..7*/ : /* vertical(0) */ +v0: skip_bits(1); + rlen = vertical_0; + break; + case 2: /* vertical(+1) */ + skip_bits(3); + rlen = vertical_0 + 1; + break; + case 3: /* vertical(-1) */ + skip_bits(3); + rlen = vertical_0 - 1; + break; + case 1: /* horizontal */ + skip_bits(3); + if (invert == invert_white) + goto hww; + else + goto hbb; + case 0: /* everything else */ + get_run(cf_2d_decode, cfd_2d_initial_bits, cfd_2d_min_bits, + rlen, "[w2]", d2l, out0); + /* rlen may be run2_pass, run_uncompressed, or */ + /* 0..countof(cf2_run_vertical)-1. */ + if (rlen < 0) + switch (rlen) { + case run2_pass: + break; + case run_uncompressed: + { + int which; + + cfd_store_state(); + which = cf_decode_uncompressed(ss, pr); + if (which < 0) { + status = which; + goto out; + } + cfd_load_state(); +/****** ADJUST count ******/ + invert = (which ? ~invert_white : invert_white); + } + goto top; + default: /* run_error, run_zeros */ + status = PTSFAX_ERRC; + goto out; + } + } + /* Interpreting the run requires scanning the */ + /* previous ('reference') line. */ + { + int prev_count = count; + unsigned char prev_data; + int dlen; + static const unsigned char count_bit[8] = + {0x80, 1, 2, 4, 8, 0x10, 0x20, 0x40}; + unsigned char *prev_q = prev_q01 + (q - q0); + int plen; + + if (!(count & 7)) + prev_q++; /* because of skip macros */ + prev_data = prev_q[-1] ^ invert; + /* Find the b1 transition. */ + if ((prev_data & count_bit[prev_count & 7]) && + (prev_count < init_count || invert != invert_white) + ) { /* Look for changing white first. */ + if_debug1('W', " data=0x%x", prev_data); + skip_black_pixels(prev_data, prev_q, + prev_count, invert, plen); + if (prev_count < end_count) /* overshot */ + prev_count = end_count; + if_debug1('W', " b1 other=%d", prev_count); + } + if (prev_count != end_count) { + if_debug1('W', " data=0x%x", prev_data); + skip_white_pixels(prev_data, prev_q, + prev_count, invert, plen); + if (prev_count < end_count) /* overshot */ + prev_count = end_count; + if_debug1('W', " b1 same=%d", prev_count); + } + /* b1 = prev_count; */ + if (rlen == run2_pass) { /* Pass mode. Find b2. */ + if (prev_count != end_count) { + if_debug1('W', " data=0x%x", prev_data); + skip_black_pixels(prev_data, prev_q, + prev_count, invert, plen); + if (prev_count < end_count) /* overshot */ + prev_count = end_count; + } + /* b2 = prev_count; */ + if_debug2('W', " b2=%d, pass %d\n", + prev_count, count - prev_count); + } else { /* Vertical coding. */ + /* Remember that count counts *down*. */ + prev_count += rlen - vertical_0; /* a1 */ + if_debug2('W', " vertical %d -> %d\n", + rlen - vertical_0, prev_count); + } + /* Now either invert or skip from count */ + /* to prev_count, and reset count. */ + if (invert == invert_white) { /* Skip data bits. */ + q = endptr - (prev_count >> 3); + qbit = prev_count & 7; + } else { /* Invert data bits. */ + dlen = count - prev_count; + invert_data(dlen, black_byte, DO_NOTHING, idd); + } + count = prev_count; + if (rlen >= 0) /* vertical mode */ + invert = ~invert; /* polarity changes */ + } + goto top; + out3: + if (bits_left > 0 && peek_bits(1)) { + /* This is a 1-bit "vertical 0" code, which we can still process. */ + goto v0; + } + /* falls through */ + out0:status = 0; + /* falls through */ + out:cfd_store_state(); + ss->invert = invert; + return status; + /* + * We handle horizontal decoding here, so that we can + * branch back into it if we run out of input data. + */ + /* White, then black. */ + hww:get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits, + rlen, " white", wwl, outww); + if ((count -= rlen) < end_count) { + status = PTSFAX_ERRC; + goto out; + } + skip_data(rlen, hww); + /* Handle the second half of a white-black horizontal code. */ + hwb:get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits, + rlen, " black", wbl, outwb); + if ((count -= rlen) < end_count) { + status = PTSFAX_ERRC; + goto out; + } + invert_data(rlen, black_byte, goto hwb, ihwb); + goto top; + outww:ss->run_color = -2; + goto out0; + outwb:ss->run_color = 1; + goto out0; + /* Black, then white. */ + hbb:get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits, + rlen, " black", bbl, outbb); + if ((count -= rlen) < end_count) { + status = PTSFAX_ERRC; + goto out; + } + invert_data(rlen, black_byte, goto hbb, ihbb); + /* Handle the second half of a black-white horizontal code. */ + hbw:get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits, + rlen, " white", bwl, outbw); + if ((count -= rlen) < end_count) { + status = PTSFAX_ERRC; + goto out; + } + skip_data(rlen, hbw); + goto top; + outbb:ss->run_color = 2; + goto out0; + outbw:ss->run_color = -1; + goto out0; +} + +#if 1 /*************** */ +static int +cf_decode_uncompressed(stream_CFD_state * ss, stream_cursor_read * pr) +{ + (void)ss; + (void)pr; + /**** pts ****/ + return PTSFAX_ERRC; +} +#else /*************** */ + +/* Decode uncompressed data. */ +/* (Not tested: no sample data available!) */ +/****** DOESN'T CHECK FOR OVERFLOWING SCAN LINE ******/ +static int +cf_decode_uncompressed(stream * s) +{ + cfd_declare_state; + const cfd_node *np; + int clen, rlen; + + cfd_load_state(); + while (1) { + ensure_bits(cfd_uncompressed_initial_bits, NOOUT); + np = &cf_uncompressed_decode[peek_bits(cfd_uncompressed_initial_bits)]; + clen = np->code_length; + rlen = np->run_length; + if (clen > cfd_uncompressed_initial_bits) { /* Must be an exit code. */ + break; + } + if (rlen == cfd_uncompressed_initial_bits) { /* Longest representable white run */ + if_debug1('W', "[wu]%d\n", rlen); + if ((qbit -= cfd_uncompressed_initial_bits) < 0) + qbit += 8, q++; + } else { + if_debug1('W', "[wu]%d+1\n", rlen); + if (qbit -= rlen < 0) + qbit += 8, q++; + *q ^= 1 << qbit; + } + skip_bits(clen); + } + clen -= cfd_uncompressed_initial_bits; + skip_bits(cfd_uncompressed_initial_bits); + ensure_bits(clen, NOOUT); + np = &cf_uncompressed_decode[rlen + peek_var_bits(clen)]; + rlen = np->run_length; + skip_bits(np->code_length); + if_debug1('w', "[wu]exit %d\n", rlen); + if (rlen >= 0) { /* Valid exit code, rlen = 2 * run length + next polarity */ + if ((qbit -= rlen >> 1) < 0) + qbit += 8, q++; + rlen &= 1; + } + out: +/******* WRONG ******/ + cfd_store_state(); + return rlen; +} + +#endif /*************** */ + +/* Move as much data as possible from one buffer to another. */ +/* Return 0 if the input became empty, 1 if the output became full. */ +int +stream_move(stream_cursor_read * pr, stream_cursor_write * pw) +{ + unsigned int rcount = pr->limit - pr->ptr; + unsigned int wcount = pw->limit - pw->ptr; + unsigned int count; + int status; + + if (rcount <= wcount) + count = rcount, status = 0; + else + count = wcount, status = 1; + + /**** pts ****/ /* Dat: memcpy should be enough instead of memmove */ + #if 0 + memmove(pw->ptr + 1, pr->ptr + 1, count); + pr->ptr += count; + pw->ptr += count; + #else + while (count--!=0) *++pw->ptr=*++pr->ptr; + #endif + return status; +} + + +#if 1 /**** pts ****/ +/* Stream template */ +const stream_template s_CFD_template = +{/*0, &st_CFD_state*/ s_CFD_init, s_CFD_process, 1, 1, s_CFD_release, + s_CFD_set_defaults, 0 +}; +#endif + +/* end of former scfd.c */ + + +#endif /* USE_BUILTIN_FAXD */ + +#if USE_BUILTIN_FAXE || USE_BUILTIN_FAXD +/* shc.c */ +/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */ +/* Support code for shc.h */ +/* #include "scommon.h" */ +/* #include "shc.h" */ +/* #include "scfx.h" */ /**** pts ****/ /* struct stream_hc_state_s */ + +/* ------ Encoding ------ */ + +/* Empty the 1-word buffer onto the output stream. */ +/* q has already been incremented. */ +static void +hc_put_code_proc(bool reverse_bits, unsigned char * q, unsigned int cw) +{ +#define cb(n) ((unsigned char)(cw >> (n * 8))) + if (reverse_bits) { +#if hc_bits_size > 16 + q[-3] = byte_reverse_bits[cb(3)]; + q[-2] = byte_reverse_bits[cb(2)]; +#endif + q[-1] = byte_reverse_bits[cb(1)]; + q[0] = byte_reverse_bits[cb(0)]; + } else { +#if hc_bits_size > 16 + q[-3] = cb(3); + q[-2] = cb(2); +#endif + q[-1] = cb(1); + q[0] = cb(0); + } +#undef cb +} + +/* Put out any final bytes. */ +/* Note that this does a store_state, but not a load_state. */ +static unsigned char * +hc_put_last_bits_proc(stream_hc_state * ss, unsigned char * q, unsigned int bits, int bits_left) +{ + while (bits_left < hc_bits_size) { + unsigned char c = (unsigned char) (bits >> (hc_bits_size - 8)); + + if (ss->FirstBitLowOrder) + c = byte_reverse_bits[c]; + *++q = c; + bits <<= 8; + bits_left += 8; + } + ss->bits = bits; + ss->bits_left = bits_left; + return q; +} + +/* end of former shc.c */ + + +/* gsbittab.c */ +/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */ +/* Tables for bit operations */ +/* #include "gstypes.h" */ +/* #include "gsbittab.h" */ + +/* ---------------- Byte processing tables ---------------- */ + +/* + * byte_reverse_bits[B] = the unsigned char B with the order of bits reversed. + */ +impl_const unsigned char byte_reverse_bits[256] = { + bit_table_8(0, 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80) +}; + +/* + * byte_right_mask[N] = a unsigned char with N trailing 1s, 0 <= N <= 8. + */ +impl_const unsigned char byte_right_mask[9] = { + 0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff +}; + +/* + * byte_count_bits[B] = the number of 1-bits in a unsigned char with value B. + */ +impl_const unsigned char byte_count_bits[256] = { + bit_table_8(0, 1, 1, 1, 1, 1, 1, 1, 1) +}; + +/* ---------------- Scanning tables ---------------- */ + +/* + * byte_bit_run_length_N[B], for 0 <= N <= 7, gives the length of the + * run of 1-bits starting at bit N in a unsigned char with value B, + * numbering the bits in the unsigned char as 01234567. If the run includes + * the low-order bit (i.e., might be continued into a following unsigned char), + * the run length is increased by 8. + */ + +#define t8(n) n,n,n,n,n+1,n+1,n+2,n+11 +#define r8(n) n,n,n,n,n,n,n,n +#define r16(n) r8(n),r8(n) +#define r32(n) r16(n),r16(n) +#define r64(n) r32(n),r32(n) +#define r128(n) r64(n),r64(n) +impl_const unsigned char byte_bit_run_length_0[256] = { + r128(0), r64(1), r32(2), r16(3), r8(4), t8(5) +}; +impl_const unsigned char byte_bit_run_length_1[256] = { + r64(0), r32(1), r16(2), r8(3), t8(4), + r64(0), r32(1), r16(2), r8(3), t8(4) +}; +impl_const unsigned char byte_bit_run_length_2[256] = { + r32(0), r16(1), r8(2), t8(3), + r32(0), r16(1), r8(2), t8(3), + r32(0), r16(1), r8(2), t8(3), + r32(0), r16(1), r8(2), t8(3) +}; +impl_const unsigned char byte_bit_run_length_3[256] = { + r16(0), r8(1), t8(2), r16(0), r8(1), t8(2), + r16(0), r8(1), t8(2), r16(0), r8(1), t8(2), + r16(0), r8(1), t8(2), r16(0), r8(1), t8(2), + r16(0), r8(1), t8(2), r16(0), r8(1), t8(2) +}; +impl_const unsigned char byte_bit_run_length_4[256] = { + r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), + r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), + r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), + r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), +}; + +#define rr8(a,b,c,d,e,f,g,h)\ + a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\ + a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\ + a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\ + a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\ + a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\ + a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\ + a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\ + a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h +impl_const unsigned char byte_bit_run_length_5[256] = { + rr8(0, 0, 0, 0, 1, 1, 2, 11) +}; +impl_const unsigned char byte_bit_run_length_6[256] = { + rr8(0, 0, 1, 10, 0, 0, 1, 10) +}; +impl_const unsigned char byte_bit_run_length_7[256] = { + rr8(0, 9, 0, 9, 0, 9, 0, 9) +}; + +/* Pointer tables indexed by bit number. */ + +impl_const unsigned char *const byte_bit_run_length[8] = { + byte_bit_run_length_0, byte_bit_run_length_1, + byte_bit_run_length_2, byte_bit_run_length_3, + byte_bit_run_length_4, byte_bit_run_length_5, + byte_bit_run_length_6, byte_bit_run_length_7 +}; +impl_const unsigned char *const byte_bit_run_length_neg[8] = { + byte_bit_run_length_0, byte_bit_run_length_7, + byte_bit_run_length_6, byte_bit_run_length_5, + byte_bit_run_length_4, byte_bit_run_length_3, + byte_bit_run_length_2, byte_bit_run_length_1 +}; + +/* + * byte_acegbdfh_to_abcdefgh[acegbdfh] = abcdefgh, where the letters + * denote the individual bits of the unsigned char. + */ +impl_const unsigned char byte_acegbdfh_to_abcdefgh[256] = { + bit_table_8(0, 0x80, 0x20, 0x08, 0x02, 0x40, 0x10, 0x04, 0x01) +}; + +#if 0 +/* Some C compilers insist on having executable code in every file.... */ +void gsbittab_dummy _((void)); /* for picky compilers */ +void +gsbittab_dummy(void) +{ +} +#endif + +/* end of former gsbittab.c */ +#endif /* USE_BUILTIN_FAXE || USE_BUILTIN_FAXD */ + +/* end of pts_fax.c */ |