roentgen b75cab
/* $Id: tif_fax3.h,v 1.9 2011-03-10 20:23:07 fwarmerdam Exp $ */
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Copyright (c) 1990-1997 Sam Leffler
roentgen b75cab
 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
roentgen b75cab
 *
roentgen b75cab
 * Permission to use, copy, modify, distribute, and sell this software and 
roentgen b75cab
 * its documentation for any purpose is hereby granted without fee, provided
roentgen b75cab
 * that (i) the above copyright notices and this permission notice appear in
roentgen b75cab
 * all copies of the software and related documentation, and (ii) the names of
roentgen b75cab
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
roentgen b75cab
 * publicity relating to the software without the specific, prior written
roentgen b75cab
 * permission of Sam Leffler and Silicon Graphics.
roentgen b75cab
 * 
roentgen b75cab
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
roentgen b75cab
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
roentgen b75cab
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
roentgen b75cab
 * 
roentgen b75cab
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
roentgen b75cab
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
roentgen b75cab
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
roentgen b75cab
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
roentgen b75cab
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
roentgen b75cab
 * OF THIS SOFTWARE.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
#ifndef _FAX3_
roentgen b75cab
#define	_FAX3_
roentgen b75cab
/*
roentgen b75cab
 * TIFF Library.
roentgen b75cab
 *
roentgen b75cab
 * CCITT Group 3 (T.4) and Group 4 (T.6) Decompression Support.
roentgen b75cab
 *
roentgen b75cab
 * Decoder support is derived, with permission, from the code
roentgen b75cab
 * in Frank Cringle's viewfax program;
roentgen b75cab
 *      Copyright (C) 1990, 1995  Frank D. Cringle.
roentgen b75cab
 */
roentgen b75cab
#include "tiff.h"
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * To override the default routine used to image decoded
roentgen b75cab
 * spans one can use the pseduo tag TIFFTAG_FAXFILLFUNC.
roentgen b75cab
 * The routine must have the type signature given below;
roentgen b75cab
 * for example:
roentgen b75cab
 *
roentgen b75cab
 * fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx)
roentgen b75cab
 *
roentgen b75cab
 * where buf is place to set the bits, runs is the array of b&w run
roentgen b75cab
 * lengths (white then black), erun is the last run in the array, and
roentgen b75cab
 * lastx is the width of the row in pixels.  Fill routines can assume
roentgen b75cab
 * the run array has room for at least lastx runs and can overwrite
roentgen b75cab
 * data in the run array as needed (e.g. to append zero runs to bring
roentgen b75cab
 * the count up to a nice multiple).
roentgen b75cab
 */
roentgen b75cab
typedef void (*TIFFFaxFillFunc)(unsigned char*, uint32*, uint32*, uint32);
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * The default run filler; made external for other decoders.
roentgen b75cab
 */
roentgen b75cab
#if defined(__cplusplus)
roentgen b75cab
extern "C" {
roentgen b75cab
#endif
roentgen b75cab
extern void _TIFFFax3fillruns(unsigned char*, uint32*, uint32*, uint32);
roentgen b75cab
#if defined(__cplusplus)
roentgen b75cab
}
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
roentgen b75cab
/* finite state machine codes */
roentgen b75cab
#define S_Null     0
roentgen b75cab
#define S_Pass     1
roentgen b75cab
#define S_Horiz    2
roentgen b75cab
#define S_V0       3
roentgen b75cab
#define S_VR       4
roentgen b75cab
#define S_VL       5
roentgen b75cab
#define S_Ext      6
roentgen b75cab
#define S_TermW    7
roentgen b75cab
#define S_TermB    8
roentgen b75cab
#define S_MakeUpW  9
roentgen b75cab
#define S_MakeUpB  10
roentgen b75cab
#define S_MakeUp   11
roentgen b75cab
#define S_EOL      12
roentgen b75cab
roentgen b75cab
typedef struct {                /* state table entry */
roentgen b75cab
	unsigned char State;    /* see above */
roentgen b75cab
	unsigned char Width;    /* width of code in bits */
roentgen b75cab
	uint32 Param;           /* unsigned 32-bit run length in bits */
roentgen b75cab
} TIFFFaxTabEnt;
roentgen b75cab
roentgen b75cab
extern const TIFFFaxTabEnt TIFFFaxMainTable[];
roentgen b75cab
extern const TIFFFaxTabEnt TIFFFaxWhiteTable[];
roentgen b75cab
extern const TIFFFaxTabEnt TIFFFaxBlackTable[];
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * The following macros define the majority of the G3/G4 decoder
roentgen b75cab
 * algorithm using the state tables defined elsewhere.  To build
roentgen b75cab
 * a decoder you need some setup code and some glue code. Note
roentgen b75cab
 * that you may also need/want to change the way the NeedBits*
roentgen b75cab
 * macros get input data if, for example, you know the data to be
roentgen b75cab
 * decoded is properly aligned and oriented (doing so before running
roentgen b75cab
 * the decoder can be a big performance win).
roentgen b75cab
 *
roentgen b75cab
 * Consult the decoder in the TIFF library for an idea of what you
roentgen b75cab
 * need to define and setup to make use of these definitions.
roentgen b75cab
 *
roentgen b75cab
 * NB: to enable a debugging version of these macros define FAX3_DEBUG
roentgen b75cab
 *     before including this file.  Trace output goes to stdout.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
#ifndef EndOfData
roentgen b75cab
#define EndOfData()	(cp >= ep)
roentgen b75cab
#endif
roentgen b75cab
/*
roentgen b75cab
 * Need <=8 or <=16 bits of input data.  Unlike viewfax we
roentgen b75cab
 * cannot use/assume a word-aligned, properly bit swizzled
roentgen b75cab
 * input data set because data may come from an arbitrarily
roentgen b75cab
 * aligned, read-only source such as a memory-mapped file.
roentgen b75cab
 * Note also that the viewfax decoder does not check for
roentgen b75cab
 * running off the end of the input data buffer.  This is
roentgen b75cab
 * possible for G3-encoded data because it prescans the input
roentgen b75cab
 * data to count EOL markers, but can cause problems for G4
roentgen b75cab
 * data.  In any event, we don't prescan and must watch for
roentgen b75cab
 * running out of data since we can't permit the library to
roentgen b75cab
 * scan past the end of the input data buffer.
roentgen b75cab
 *
roentgen b75cab
 * Finally, note that we must handle remaindered data at the end
roentgen b75cab
 * of a strip specially.  The coder asks for a fixed number of
roentgen b75cab
 * bits when scanning for the next code.  This may be more bits
roentgen b75cab
 * than are actually present in the data stream.  If we appear
roentgen b75cab
 * to run out of data but still have some number of valid bits
roentgen b75cab
 * remaining then we makeup the requested amount with zeros and
roentgen b75cab
 * return successfully.  If the returned data is incorrect then
roentgen b75cab
 * we should be called again and get a premature EOF error;
roentgen b75cab
 * otherwise we should get the right answer.
roentgen b75cab
 */
roentgen b75cab
#ifndef NeedBits8
roentgen b75cab
#define NeedBits8(n,eoflab) do {					\
roentgen b75cab
    if (BitsAvail < (n)) {						\
roentgen b75cab
	if (EndOfData()) {						\
roentgen b75cab
	    if (BitsAvail == 0)			/* no valid bits */	\
roentgen b75cab
		goto eoflab;						\
roentgen b75cab
	    BitsAvail = (n);			/* pad with zeros */	\
roentgen b75cab
	} else {							\
roentgen b75cab
	    BitAcc |= ((uint32) bitmap[*cp++])<
roentgen b75cab
	    BitsAvail += 8;						\
roentgen b75cab
	}								\
roentgen b75cab
    }									\
roentgen b75cab
} while (0)
roentgen b75cab
#endif
roentgen b75cab
#ifndef NeedBits16
roentgen b75cab
#define NeedBits16(n,eoflab) do {					\
roentgen b75cab
    if (BitsAvail < (n)) {						\
roentgen b75cab
	if (EndOfData()) {						\
roentgen b75cab
	    if (BitsAvail == 0)			/* no valid bits */	\
roentgen b75cab
		goto eoflab;						\
roentgen b75cab
	    BitsAvail = (n);			/* pad with zeros */	\
roentgen b75cab
	} else {							\
roentgen b75cab
	    BitAcc |= ((uint32) bitmap[*cp++])<
roentgen b75cab
	    if ((BitsAvail += 8) < (n)) {				\
roentgen b75cab
		if (EndOfData()) {					\
roentgen b75cab
		    /* NB: we know BitsAvail is non-zero here */	\
roentgen b75cab
		    BitsAvail = (n);		/* pad with zeros */	\
roentgen b75cab
		} else {						\
roentgen b75cab
		    BitAcc |= ((uint32) bitmap[*cp++])<
roentgen b75cab
		    BitsAvail += 8;					\
roentgen b75cab
		}							\
roentgen b75cab
	    }								\
roentgen b75cab
	}								\
roentgen b75cab
    }									\
roentgen b75cab
} while (0)
roentgen b75cab
#endif
roentgen b75cab
#define GetBits(n)	(BitAcc & ((1<<(n))-1))
roentgen b75cab
#define ClrBits(n) do {							\
roentgen b75cab
    BitsAvail -= (n);							\
roentgen b75cab
    BitAcc >>= (n);							\
roentgen b75cab
} while (0)
roentgen b75cab
roentgen b75cab
#ifdef FAX3_DEBUG
roentgen b75cab
static const char* StateNames[] = {
roentgen b75cab
    "Null   ",
roentgen b75cab
    "Pass   ",
roentgen b75cab
    "Horiz  ",
roentgen b75cab
    "V0     ",
roentgen b75cab
    "VR     ",
roentgen b75cab
    "VL     ",
roentgen b75cab
    "Ext    ",
roentgen b75cab
    "TermW  ",
roentgen b75cab
    "TermB  ",
roentgen b75cab
    "MakeUpW",
roentgen b75cab
    "MakeUpB",
roentgen b75cab
    "MakeUp ",
roentgen b75cab
    "EOL    ",
roentgen b75cab
};
roentgen b75cab
#define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0')
roentgen b75cab
#define LOOKUP8(wid,tab,eoflab) do {					\
roentgen b75cab
    int t;								\
roentgen b75cab
    NeedBits8(wid,eoflab);						\
roentgen b75cab
    TabEnt = tab + GetBits(wid);					\
roentgen b75cab
    printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail,		\
roentgen b75cab
	   StateNames[TabEnt->State], TabEnt->Param);			\
roentgen b75cab
    for (t = 0; t < TabEnt->Width; t++)					\
roentgen b75cab
	DEBUG_SHOW;							\
roentgen b75cab
    putchar('\n');							\
roentgen b75cab
    fflush(stdout);							\
roentgen b75cab
    ClrBits(TabEnt->Width);						\
roentgen b75cab
} while (0)
roentgen b75cab
#define LOOKUP16(wid,tab,eoflab) do {					\
roentgen b75cab
    int t;								\
roentgen b75cab
    NeedBits16(wid,eoflab);						\
roentgen b75cab
    TabEnt = tab + GetBits(wid);					\
roentgen b75cab
    printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail,		\
roentgen b75cab
	   StateNames[TabEnt->State], TabEnt->Param);			\
roentgen b75cab
    for (t = 0; t < TabEnt->Width; t++)					\
roentgen b75cab
	DEBUG_SHOW;							\
roentgen b75cab
    putchar('\n');							\
roentgen b75cab
    fflush(stdout);							\
roentgen b75cab
    ClrBits(TabEnt->Width);						\
roentgen b75cab
} while (0)
roentgen b75cab
roentgen b75cab
#define SETVALUE(x) do {							\
roentgen b75cab
    *pa++ = RunLength + (x);						\
roentgen b75cab
    printf("SETVALUE: %d\t%d\n", RunLength + (x), a0);			\
roentgen b75cab
    a0 += x;								\
roentgen b75cab
    RunLength = 0;							\
roentgen b75cab
} while (0)
roentgen b75cab
#else
roentgen b75cab
#define LOOKUP8(wid,tab,eoflab) do {					\
roentgen b75cab
    NeedBits8(wid,eoflab);						\
roentgen b75cab
    TabEnt = tab + GetBits(wid);					\
roentgen b75cab
    ClrBits(TabEnt->Width);						\
roentgen b75cab
} while (0)
roentgen b75cab
#define LOOKUP16(wid,tab,eoflab) do {					\
roentgen b75cab
    NeedBits16(wid,eoflab);						\
roentgen b75cab
    TabEnt = tab + GetBits(wid);					\
roentgen b75cab
    ClrBits(TabEnt->Width);						\
roentgen b75cab
} while (0)
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Append a run to the run length array for the
roentgen b75cab
 * current row and reset decoding state.
roentgen b75cab
 */
roentgen b75cab
#define SETVALUE(x) do {							\
roentgen b75cab
    *pa++ = RunLength + (x);						\
roentgen b75cab
    a0 += (x);								\
roentgen b75cab
    RunLength = 0;							\
roentgen b75cab
} while (0)
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Synchronize input decoding at the start of each
roentgen b75cab
 * row by scanning for an EOL (if appropriate) and
roentgen b75cab
 * skipping any trash data that might be present
roentgen b75cab
 * after a decoding error.  Note that the decoding
roentgen b75cab
 * done elsewhere that recognizes an EOL only consumes
roentgen b75cab
 * 11 consecutive zero bits.  This means that if EOLcnt
roentgen b75cab
 * is non-zero then we still need to scan for the final flag
roentgen b75cab
 * bit that is part of the EOL code.
roentgen b75cab
 */
roentgen b75cab
#define	SYNC_EOL(eoflab) do {						\
roentgen b75cab
    if (EOLcnt == 0) {							\
roentgen b75cab
	for (;;) {							\
roentgen b75cab
	    NeedBits16(11,eoflab);					\
roentgen b75cab
	    if (GetBits(11) == 0)					\
roentgen b75cab
		break;							\
roentgen b75cab
	    ClrBits(1);							\
roentgen b75cab
	}								\
roentgen b75cab
    }									\
roentgen b75cab
    for (;;) {								\
roentgen b75cab
	NeedBits8(8,eoflab);						\
roentgen b75cab
	if (GetBits(8))							\
roentgen b75cab
	    break;							\
roentgen b75cab
	ClrBits(8);							\
roentgen b75cab
    }									\
roentgen b75cab
    while (GetBits(1) == 0)						\
roentgen b75cab
	ClrBits(1);							\
roentgen b75cab
    ClrBits(1);				/* EOL bit */			\
roentgen b75cab
    EOLcnt = 0;				/* reset EOL counter/flag */	\
roentgen b75cab
} while (0)
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Cleanup the array of runs after decoding a row.
roentgen b75cab
 * We adjust final runs to insure the user buffer is not
roentgen b75cab
 * overwritten and/or undecoded area is white filled.
roentgen b75cab
 */
roentgen b75cab
#define	CLEANUP_RUNS() do {						\
roentgen b75cab
    if (RunLength)							\
roentgen b75cab
	SETVALUE(0);							\
roentgen b75cab
    if (a0 != lastx) {							\
roentgen b75cab
	badlength(a0, lastx);						\
roentgen b75cab
	while (a0 > lastx && pa > thisrun)				\
roentgen b75cab
	    a0 -= *--pa;						\
roentgen b75cab
	if (a0 < lastx) {						\
roentgen b75cab
	    if (a0 < 0)							\
roentgen b75cab
		a0 = 0;							\
roentgen b75cab
	    if ((pa-thisrun)&1)						\
roentgen b75cab
		SETVALUE(0);						\
roentgen b75cab
	    SETVALUE(lastx - a0);						\
roentgen b75cab
	} else if (a0 > lastx) {					\
roentgen b75cab
	    SETVALUE(lastx);						\
roentgen b75cab
	    SETVALUE(0);							\
roentgen b75cab
	}								\
roentgen b75cab
    }									\
roentgen b75cab
} while (0)
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Decode a line of 1D-encoded data.
roentgen b75cab
 *
roentgen b75cab
 * The line expanders are written as macros so that they can be reused
roentgen b75cab
 * but still have direct access to the local variables of the "calling"
roentgen b75cab
 * function.
roentgen b75cab
 *
roentgen b75cab
 * Note that unlike the original version we have to explicitly test for
roentgen b75cab
 * a0 >= lastx after each black/white run is decoded.  This is because
roentgen b75cab
 * the original code depended on the input data being zero-padded to
roentgen b75cab
 * insure the decoder recognized an EOL before running out of data.
roentgen b75cab
 */
roentgen b75cab
#define EXPAND1D(eoflab) do {						\
roentgen b75cab
    for (;;) {								\
roentgen b75cab
	for (;;) {							\
roentgen b75cab
	    LOOKUP16(12, TIFFFaxWhiteTable, eof1d);			\
roentgen b75cab
	    switch (TabEnt->State) {					\
roentgen b75cab
	    case S_EOL:							\
roentgen b75cab
		EOLcnt = 1;						\
roentgen b75cab
		goto done1d;						\
roentgen b75cab
	    case S_TermW:						\
roentgen b75cab
		SETVALUE(TabEnt->Param);					\
roentgen b75cab
		goto doneWhite1d;					\
roentgen b75cab
	    case S_MakeUpW:						\
roentgen b75cab
	    case S_MakeUp:						\
roentgen b75cab
		a0 += TabEnt->Param;					\
roentgen b75cab
		RunLength += TabEnt->Param;				\
roentgen b75cab
		break;							\
roentgen b75cab
	    default:							\
roentgen b75cab
		unexpected("WhiteTable", a0);				\
roentgen b75cab
		goto done1d;						\
roentgen b75cab
	    }								\
roentgen b75cab
	}								\
roentgen b75cab
    doneWhite1d:							\
roentgen b75cab
	if (a0 >= lastx)						\
roentgen b75cab
	    goto done1d;						\
roentgen b75cab
	for (;;) {							\
roentgen b75cab
	    LOOKUP16(13, TIFFFaxBlackTable, eof1d);			\
roentgen b75cab
	    switch (TabEnt->State) {					\
roentgen b75cab
	    case S_EOL:							\
roentgen b75cab
		EOLcnt = 1;						\
roentgen b75cab
		goto done1d;						\
roentgen b75cab
	    case S_TermB:						\
roentgen b75cab
		SETVALUE(TabEnt->Param);					\
roentgen b75cab
		goto doneBlack1d;					\
roentgen b75cab
	    case S_MakeUpB:						\
roentgen b75cab
	    case S_MakeUp:						\
roentgen b75cab
		a0 += TabEnt->Param;					\
roentgen b75cab
		RunLength += TabEnt->Param;				\
roentgen b75cab
		break;							\
roentgen b75cab
	    default:							\
roentgen b75cab
		unexpected("BlackTable", a0);				\
roentgen b75cab
		goto done1d;						\
roentgen b75cab
	    }								\
roentgen b75cab
	}								\
roentgen b75cab
    doneBlack1d:							\
roentgen b75cab
	if (a0 >= lastx)						\
roentgen b75cab
	    goto done1d;						\
roentgen b75cab
        if( *(pa-1) == 0 && *(pa-2) == 0 )				\
roentgen b75cab
            pa -= 2;                                                    \
roentgen b75cab
    }									\
roentgen b75cab
eof1d:									\
roentgen b75cab
    prematureEOF(a0);							\
roentgen b75cab
    CLEANUP_RUNS();							\
roentgen b75cab
    goto eoflab;							\
roentgen b75cab
done1d:									\
roentgen b75cab
    CLEANUP_RUNS();							\
roentgen b75cab
} while (0)
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Update the value of b1 using the array
roentgen b75cab
 * of runs for the reference line.
roentgen b75cab
 */
roentgen b75cab
#define CHECK_b1 do {							\
roentgen b75cab
    if (pa != thisrun) while (b1 <= a0 && b1 < lastx) {			\
roentgen b75cab
	b1 += pb[0] + pb[1];						\
roentgen b75cab
	pb += 2;							\
roentgen b75cab
    }									\
roentgen b75cab
} while (0)
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Expand a row of 2D-encoded data.
roentgen b75cab
 */
roentgen b75cab
#define EXPAND2D(eoflab) do {						\
roentgen b75cab
    while (a0 < lastx) {						\
roentgen b75cab
	LOOKUP8(7, TIFFFaxMainTable, eof2d);				\
roentgen b75cab
	switch (TabEnt->State) {					\
roentgen b75cab
	case S_Pass:							\
roentgen b75cab
	    CHECK_b1;							\
roentgen b75cab
	    b1 += *pb++;						\
roentgen b75cab
	    RunLength += b1 - a0;					\
roentgen b75cab
	    a0 = b1;							\
roentgen b75cab
	    b1 += *pb++;						\
roentgen b75cab
	    break;							\
roentgen b75cab
	case S_Horiz:							\
roentgen b75cab
	    if ((pa-thisrun)&1) {					\
roentgen b75cab
		for (;;) {	/* black first */			\
roentgen b75cab
		    LOOKUP16(13, TIFFFaxBlackTable, eof2d);		\
roentgen b75cab
		    switch (TabEnt->State) {				\
roentgen b75cab
		    case S_TermB:					\
roentgen b75cab
			SETVALUE(TabEnt->Param);				\
roentgen b75cab
			goto doneWhite2da;				\
roentgen b75cab
		    case S_MakeUpB:					\
roentgen b75cab
		    case S_MakeUp:					\
roentgen b75cab
			a0 += TabEnt->Param;				\
roentgen b75cab
			RunLength += TabEnt->Param;			\
roentgen b75cab
			break;						\
roentgen b75cab
		    default:						\
roentgen b75cab
			goto badBlack2d;				\
roentgen b75cab
		    }							\
roentgen b75cab
		}							\
roentgen b75cab
	    doneWhite2da:;						\
roentgen b75cab
		for (;;) {	/* then white */			\
roentgen b75cab
		    LOOKUP16(12, TIFFFaxWhiteTable, eof2d);		\
roentgen b75cab
		    switch (TabEnt->State) {				\
roentgen b75cab
		    case S_TermW:					\
roentgen b75cab
			SETVALUE(TabEnt->Param);				\
roentgen b75cab
			goto doneBlack2da;				\
roentgen b75cab
		    case S_MakeUpW:					\
roentgen b75cab
		    case S_MakeUp:					\
roentgen b75cab
			a0 += TabEnt->Param;				\
roentgen b75cab
			RunLength += TabEnt->Param;			\
roentgen b75cab
			break;						\
roentgen b75cab
		    default:						\
roentgen b75cab
			goto badWhite2d;				\
roentgen b75cab
		    }							\
roentgen b75cab
		}							\
roentgen b75cab
	    doneBlack2da:;						\
roentgen b75cab
	    } else {							\
roentgen b75cab
		for (;;) {	/* white first */			\
roentgen b75cab
		    LOOKUP16(12, TIFFFaxWhiteTable, eof2d);		\
roentgen b75cab
		    switch (TabEnt->State) {				\
roentgen b75cab
		    case S_TermW:					\
roentgen b75cab
			SETVALUE(TabEnt->Param);				\
roentgen b75cab
			goto doneWhite2db;				\
roentgen b75cab
		    case S_MakeUpW:					\
roentgen b75cab
		    case S_MakeUp:					\
roentgen b75cab
			a0 += TabEnt->Param;				\
roentgen b75cab
			RunLength += TabEnt->Param;			\
roentgen b75cab
			break;						\
roentgen b75cab
		    default:						\
roentgen b75cab
			goto badWhite2d;				\
roentgen b75cab
		    }							\
roentgen b75cab
		}							\
roentgen b75cab
	    doneWhite2db:;						\
roentgen b75cab
		for (;;) {	/* then black */			\
roentgen b75cab
		    LOOKUP16(13, TIFFFaxBlackTable, eof2d);		\
roentgen b75cab
		    switch (TabEnt->State) {				\
roentgen b75cab
		    case S_TermB:					\
roentgen b75cab
			SETVALUE(TabEnt->Param);				\
roentgen b75cab
			goto doneBlack2db;				\
roentgen b75cab
		    case S_MakeUpB:					\
roentgen b75cab
		    case S_MakeUp:					\
roentgen b75cab
			a0 += TabEnt->Param;				\
roentgen b75cab
			RunLength += TabEnt->Param;			\
roentgen b75cab
			break;						\
roentgen b75cab
		    default:						\
roentgen b75cab
			goto badBlack2d;				\
roentgen b75cab
		    }							\
roentgen b75cab
		}							\
roentgen b75cab
	    doneBlack2db:;						\
roentgen b75cab
	    }								\
roentgen b75cab
	    CHECK_b1;							\
roentgen b75cab
	    break;							\
roentgen b75cab
	case S_V0:							\
roentgen b75cab
	    CHECK_b1;							\
roentgen b75cab
	    SETVALUE(b1 - a0);						\
roentgen b75cab
	    b1 += *pb++;						\
roentgen b75cab
	    break;							\
roentgen b75cab
	case S_VR:							\
roentgen b75cab
	    CHECK_b1;							\
roentgen b75cab
	    SETVALUE(b1 - a0 + TabEnt->Param);				\
roentgen b75cab
	    b1 += *pb++;						\
roentgen b75cab
	    break;							\
roentgen b75cab
	case S_VL:							\
roentgen b75cab
	    CHECK_b1;							\
roentgen b75cab
	    if (b1 <= (int) (a0 + TabEnt->Param)) {			\
roentgen b75cab
		if (b1 < (int) (a0 + TabEnt->Param) || pa != thisrun) {	\
roentgen b75cab
		    unexpected("VL", a0);				\
roentgen b75cab
		    goto eol2d;						\
roentgen b75cab
		}							\
roentgen b75cab
	    }								\
roentgen b75cab
	    SETVALUE(b1 - a0 - TabEnt->Param);				\
roentgen b75cab
	    b1 -= *--pb;						\
roentgen b75cab
	    break;							\
roentgen b75cab
	case S_Ext:							\
roentgen b75cab
	    *pa++ = lastx - a0;						\
roentgen b75cab
	    extension(a0);						\
roentgen b75cab
	    goto eol2d;							\
roentgen b75cab
	case S_EOL:							\
roentgen b75cab
	    *pa++ = lastx - a0;						\
roentgen b75cab
	    NeedBits8(4,eof2d);						\
roentgen b75cab
	    if (GetBits(4))						\
roentgen b75cab
		unexpected("EOL", a0);					\
roentgen b75cab
            ClrBits(4);                                                 \
roentgen b75cab
	    EOLcnt = 1;							\
roentgen b75cab
	    goto eol2d;							\
roentgen b75cab
	default:							\
roentgen b75cab
	badMain2d:							\
roentgen b75cab
	    unexpected("MainTable", a0);				\
roentgen b75cab
	    goto eol2d;							\
roentgen b75cab
	badBlack2d:							\
roentgen b75cab
	    unexpected("BlackTable", a0);				\
roentgen b75cab
	    goto eol2d;							\
roentgen b75cab
	badWhite2d:							\
roentgen b75cab
	    unexpected("WhiteTable", a0);				\
roentgen b75cab
	    goto eol2d;							\
roentgen b75cab
	eof2d:								\
roentgen b75cab
	    prematureEOF(a0);						\
roentgen b75cab
	    CLEANUP_RUNS();						\
roentgen b75cab
	    goto eoflab;						\
roentgen b75cab
	}								\
roentgen b75cab
    }									\
roentgen b75cab
    if (RunLength) {							\
roentgen b75cab
	if (RunLength + a0 < lastx) {					\
roentgen b75cab
	    /* expect a final V0 */					\
roentgen b75cab
	    NeedBits8(1,eof2d);						\
roentgen b75cab
	    if (!GetBits(1))						\
roentgen b75cab
		goto badMain2d;						\
roentgen b75cab
	    ClrBits(1);							\
roentgen b75cab
	}								\
roentgen b75cab
	SETVALUE(0);							\
roentgen b75cab
    }									\
roentgen b75cab
eol2d:									\
roentgen b75cab
    CLEANUP_RUNS();							\
roentgen b75cab
} while (0)
roentgen b75cab
#endif /* _FAX3_ */
roentgen b75cab
/*
roentgen b75cab
 * Local Variables:
roentgen b75cab
 * mode: c
roentgen b75cab
 * c-basic-offset: 8
roentgen b75cab
 * fill-column: 78
roentgen b75cab
 * End:
roentgen b75cab
 */