text: /* Id */
  
  /*
   * 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_ */
  