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