removed outdated files
[swftools.git] / pdf2swf / xpdf / Stream.cc
diff --git a/pdf2swf/xpdf/Stream.cc b/pdf2swf/xpdf/Stream.cc
deleted file mode 100644 (file)
index 3306279..0000000
+++ /dev/null
@@ -1,4572 +0,0 @@
-//========================================================================
-//
-// Stream.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#ifndef WIN32
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <ctype.h>
-#include "gmem.h"
-#include "gfile.h"
-#include "config.h"
-#include "Error.h"
-#include "Object.h"
-#include "Lexer.h"
-#include "Decrypt.h"
-#include "GfxState.h"
-#include "Stream.h"
-#include "JBIG2Stream.h"
-#include "JPXStream.h"
-#include "Stream-CCITT.h"
-
-#ifdef __DJGPP__
-static GBool setDJSYSFLAGS = gFalse;
-#endif
-
-#ifdef VMS
-#ifdef __GNUC__
-#define SEEK_SET 0
-#define SEEK_CUR 1
-#define SEEK_END 2
-#endif
-#endif
-
-//------------------------------------------------------------------------
-// Stream (base class)
-//------------------------------------------------------------------------
-
-Stream::Stream() {
-  ref = 1;
-}
-
-Stream::~Stream() {
-}
-
-void Stream::close() {
-}
-
-int Stream::getRawChar() {
-  error(-1, "Internal: called getRawChar() on non-predictor stream");
-  return EOF;
-}
-
-char *Stream::getLine(char *buf, int size) {
-  int i;
-  int c;
-
-  if (lookChar() == EOF)
-    return NULL;
-  for (i = 0; i < size - 1; ++i) {
-    c = getChar();
-    if (c == EOF || c == '\n')
-      break;
-    if (c == '\r') {
-      if ((c = lookChar()) == '\n')
-       getChar();
-      break;
-    }
-    buf[i] = c;
-  }
-  buf[i] = '\0';
-  return buf;
-}
-
-GString *Stream::getPSFilter(int psLevel, char *indent) {
-  return new GString();
-}
-
-Stream *Stream::addFilters(Object *dict) {
-  Object obj, obj2;
-  Object params, params2;
-  Stream *str;
-  int i;
-
-  str = this;
-  dict->dictLookup("Filter", &obj);
-  if (obj.isNull()) {
-    obj.free();
-    dict->dictLookup("F", &obj);
-  }
-  dict->dictLookup("DecodeParms", &params);
-  if (params.isNull()) {
-    params.free();
-    dict->dictLookup("DP", &params);
-  }
-  if (obj.isName()) {
-    str = makeFilter(obj.getName(), str, &params);
-  } else if (obj.isArray()) {
-    for (i = 0; i < obj.arrayGetLength(); ++i) {
-      obj.arrayGet(i, &obj2);
-      if (params.isArray())
-       params.arrayGet(i, &params2);
-      else
-       params2.initNull();
-      if (obj2.isName()) {
-       str = makeFilter(obj2.getName(), str, &params2);
-      } else {
-       error(getPos(), "Bad filter name");
-       str = new EOFStream(str);
-      }
-      obj2.free();
-      params2.free();
-    }
-  } else if (!obj.isNull()) {
-    error(getPos(), "Bad 'Filter' attribute in stream");
-  }
-  obj.free();
-  params.free();
-
-  return str;
-}
-
-Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
-  int pred;                    // parameters
-  int colors;
-  int bits;
-  int early;
-  int encoding;
-  GBool endOfLine, byteAlign, endOfBlock, black;
-  int columns, rows;
-  Object globals, obj;
-
-  if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
-    str = new ASCIIHexStream(str);
-  } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
-    str = new ASCII85Stream(str);
-  } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
-    pred = 1;
-    columns = 1;
-    colors = 1;
-    bits = 8;
-    early = 1;
-    if (params->isDict()) {
-      params->dictLookup("Predictor", &obj);
-      if (obj.isInt())
-       pred = obj.getInt();
-      obj.free();
-      params->dictLookup("Columns", &obj);
-      if (obj.isInt())
-       columns = obj.getInt();
-      obj.free();
-      params->dictLookup("Colors", &obj);
-      if (obj.isInt())
-       colors = obj.getInt();
-      obj.free();
-      params->dictLookup("BitsPerComponent", &obj);
-      if (obj.isInt())
-       bits = obj.getInt();
-      obj.free();
-      params->dictLookup("EarlyChange", &obj);
-      if (obj.isInt())
-       early = obj.getInt();
-      obj.free();
-    }
-    str = new LZWStream(str, pred, columns, colors, bits, early);
-  } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
-    str = new RunLengthStream(str);
-  } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
-    encoding = 0;
-    endOfLine = gFalse;
-    byteAlign = gFalse;
-    columns = 1728;
-    rows = 0;
-    endOfBlock = gTrue;
-    black = gFalse;
-    if (params->isDict()) {
-      params->dictLookup("K", &obj);
-      if (obj.isInt()) {
-       encoding = obj.getInt();
-      }
-      obj.free();
-      params->dictLookup("EndOfLine", &obj);
-      if (obj.isBool()) {
-       endOfLine = obj.getBool();
-      }
-      obj.free();
-      params->dictLookup("EncodedByteAlign", &obj);
-      if (obj.isBool()) {
-       byteAlign = obj.getBool();
-      }
-      obj.free();
-      params->dictLookup("Columns", &obj);
-      if (obj.isInt()) {
-       columns = obj.getInt();
-      }
-      obj.free();
-      params->dictLookup("Rows", &obj);
-      if (obj.isInt()) {
-       rows = obj.getInt();
-      }
-      obj.free();
-      params->dictLookup("EndOfBlock", &obj);
-      if (obj.isBool()) {
-       endOfBlock = obj.getBool();
-      }
-      obj.free();
-      params->dictLookup("BlackIs1", &obj);
-      if (obj.isBool()) {
-       black = obj.getBool();
-      }
-      obj.free();
-    }
-    str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
-                            columns, rows, endOfBlock, black);
-  } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
-    str = new DCTStream(str);
-  } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
-    pred = 1;
-    columns = 1;
-    colors = 1;
-    bits = 8;
-    if (params->isDict()) {
-      params->dictLookup("Predictor", &obj);
-      if (obj.isInt())
-       pred = obj.getInt();
-      obj.free();
-      params->dictLookup("Columns", &obj);
-      if (obj.isInt())
-       columns = obj.getInt();
-      obj.free();
-      params->dictLookup("Colors", &obj);
-      if (obj.isInt())
-       colors = obj.getInt();
-      obj.free();
-      params->dictLookup("BitsPerComponent", &obj);
-      if (obj.isInt())
-       bits = obj.getInt();
-      obj.free();
-    }
-    str = new FlateStream(str, pred, columns, colors, bits);
-  } else if (!strcmp(name, "JBIG2Decode")) {
-    if (params->isDict()) {
-      params->dictLookup("JBIG2Globals", &globals);
-    }
-    str = new JBIG2Stream(str, &globals);
-    globals.free();
-  } else if (!strcmp(name, "JPXDecode")) {
-    str = new JPXStream(str);
-  } else {
-    error(getPos(), "Unknown filter '%s'", name);
-    str = new EOFStream(str);
-  }
-  return str;
-}
-
-//------------------------------------------------------------------------
-// BaseStream
-//------------------------------------------------------------------------
-
-BaseStream::BaseStream(Object *dictA) {
-  dict = *dictA;
-  decrypt = NULL;
-}
-
-BaseStream::~BaseStream() {
-  dict.free();
-  if (decrypt)
-    delete decrypt;
-}
-
-void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
-                             int objNum, int objGen) {
-  decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
-}
-
-//------------------------------------------------------------------------
-// FilterStream
-//------------------------------------------------------------------------
-
-FilterStream::FilterStream(Stream *strA) {
-  str = strA;
-}
-
-FilterStream::~FilterStream() {
-}
-
-void FilterStream::close() {
-  str->close();
-}
-
-void FilterStream::setPos(Guint pos, int dir) {
-  error(-1, "Internal: called setPos() on FilterStream");
-}
-
-//------------------------------------------------------------------------
-// ImageStream
-//------------------------------------------------------------------------
-
-ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
-  int imgLineSize;
-
-  str = strA;
-  width = widthA;
-  nComps = nCompsA;
-  nBits = nBitsA;
-
-  nVals = width * nComps;
-  if (nBits == 1) {
-    imgLineSize = (nVals + 7) & ~7;
-  } else {
-    imgLineSize = nVals;
-  }
-  imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar));
-  imgIdx = nVals;
-}
-
-ImageStream::~ImageStream() {
-  gfree(imgLine);
-}
-
-void ImageStream::reset() {
-  str->reset();
-}
-
-GBool ImageStream::getPixel(Guchar *pix) {
-  int i;
-
-  if (imgIdx >= nVals) {
-    getLine();
-    imgIdx = 0;
-  }
-  for (i = 0; i < nComps; ++i) {
-    pix[i] = imgLine[imgIdx++];
-  }
-  return gTrue;
-}
-
-Guchar *ImageStream::getLine() {
-  Gulong buf, bitMask;
-  int bits;
-  int c;
-  int i;
-
-  if (nBits == 1) {
-    for (i = 0; i < nVals; i += 8) {
-      c = str->getChar();
-      imgLine[i+0] = (Guchar)((c >> 7) & 1);
-      imgLine[i+1] = (Guchar)((c >> 6) & 1);
-      imgLine[i+2] = (Guchar)((c >> 5) & 1);
-      imgLine[i+3] = (Guchar)((c >> 4) & 1);
-      imgLine[i+4] = (Guchar)((c >> 3) & 1);
-      imgLine[i+5] = (Guchar)((c >> 2) & 1);
-      imgLine[i+6] = (Guchar)((c >> 1) & 1);
-      imgLine[i+7] = (Guchar)(c & 1);
-    }
-  } else if (nBits == 8) {
-    for (i = 0; i < nVals; ++i) {
-      imgLine[i] = str->getChar();
-    }
-  } else {
-    bitMask = (1 << nBits) - 1;
-    buf = 0;
-    bits = 0;
-    for (i = 0; i < nVals; ++i) {
-      if (bits < nBits) {
-       buf = (buf << 8) | (str->getChar() & 0xff);
-       bits += 8;
-      }
-      imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
-      bits -= nBits;
-    }
-  }
-  return imgLine;
-}
-
-void ImageStream::skipLine() {
-  int n, i;
-
-  n = (nVals * nBits + 7) >> 3;
-  for (i = 0; i < n; ++i) {
-    str->getChar();
-  }
-}
-
-//------------------------------------------------------------------------
-// StreamPredictor
-//------------------------------------------------------------------------
-
-StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
-                                int widthA, int nCompsA, int nBitsA) {
-  int totalBits;
-
-  str = strA;
-  predictor = predictorA;
-  width = widthA;
-  nComps = nCompsA;
-  nBits = nBitsA;
-  predLine = NULL;
-  ok = gFalse;
-
-  nVals = width * nComps;
-  totalBits = nVals * nBits;
-  if (totalBits == 0 ||
-      (totalBits / nBits) / nComps != width ||
-      totalBits + 7 < 0) {
-    return;
-  }
-  pixBytes = (nComps * nBits + 7) >> 3;
-  rowBytes = ((totalBits + 7) >> 3) + pixBytes;
-  if (rowBytes < 0) {
-    return;
-  }
-  predLine = (Guchar *)gmalloc(rowBytes);
-  memset(predLine, 0, rowBytes);
-  predIdx = rowBytes;
-
-  ok = gTrue;
-}
-
-StreamPredictor::~StreamPredictor() {
-  gfree(predLine);
-}
-
-int StreamPredictor::lookChar() {
-  if (predIdx >= rowBytes) {
-    if (!getNextLine()) {
-      return EOF;
-    }
-  }
-  return predLine[predIdx];
-}
-
-int StreamPredictor::getChar() {
-  if (predIdx >= rowBytes) {
-    if (!getNextLine()) {
-      return EOF;
-    }
-  }
-  return predLine[predIdx++];
-}
-
-GBool StreamPredictor::getNextLine() {
-  int curPred;
-  Guchar upLeftBuf[gfxColorMaxComps * 2 + 1];
-  int left, up, upLeft, p, pa, pb, pc;
-  int c;
-  Gulong inBuf, outBuf, bitMask;
-  int inBits, outBits;
-  int i, j, k, kk;
-
-  // get PNG optimum predictor number
-  if (predictor >= 10) {
-    if ((curPred = str->getRawChar()) == EOF) {
-      return gFalse;
-    }
-    curPred += 10;
-  } else {
-    curPred = predictor;
-  }
-
-  // read the raw line, apply PNG (byte) predictor
-  memset(upLeftBuf, 0, pixBytes + 1);
-  for (i = pixBytes; i < rowBytes; ++i) {
-    for (j = pixBytes; j > 0; --j) {
-      upLeftBuf[j] = upLeftBuf[j-1];
-    }
-    upLeftBuf[0] = predLine[i];
-    if ((c = str->getRawChar()) == EOF) {
-      if (i > pixBytes) {
-       // this ought to return false, but some (broken) PDF files
-       // contain truncated image data, and Adobe apparently reads the
-       // last partial line
-       break;
-      }
-      return gFalse;
-    }
-    switch (curPred) {
-    case 11:                   // PNG sub
-      predLine[i] = predLine[i - pixBytes] + (Guchar)c;
-      break;
-    case 12:                   // PNG up
-      predLine[i] = predLine[i] + (Guchar)c;
-      break;
-    case 13:                   // PNG average
-      predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
-                   (Guchar)c;
-      break;
-    case 14:                   // PNG Paeth
-      left = predLine[i - pixBytes];
-      up = predLine[i];
-      upLeft = upLeftBuf[pixBytes];
-      p = left + up - upLeft;
-      if ((pa = p - left) < 0)
-       pa = -pa;
-      if ((pb = p - up) < 0)
-       pb = -pb;
-      if ((pc = p - upLeft) < 0)
-       pc = -pc;
-      if (pa <= pb && pa <= pc)
-       predLine[i] = left + (Guchar)c;
-      else if (pb <= pc)
-       predLine[i] = up + (Guchar)c;
-      else
-       predLine[i] = upLeft + (Guchar)c;
-      break;
-    case 10:                   // PNG none
-    default:                   // no predictor or TIFF predictor
-      predLine[i] = (Guchar)c;
-      break;
-    }
-  }
-
-  // apply TIFF (component) predictor
-  if (predictor == 2) {
-    if (nBits == 1) {
-      inBuf = predLine[pixBytes - 1];
-      for (i = pixBytes; i < rowBytes; i += 8) {
-       // 1-bit add is just xor
-       inBuf = (inBuf << 8) | predLine[i];
-       predLine[i] ^= inBuf >> nComps;
-      }
-    } else if (nBits == 8) {
-      for (i = pixBytes; i < rowBytes; ++i) {
-       predLine[i] += predLine[i - nComps];
-      }
-    } else {
-      memset(upLeftBuf, 0, nComps + 1);
-      bitMask = (1 << nBits) - 1;
-      inBuf = outBuf = 0;
-      inBits = outBits = 0;
-      j = k = pixBytes;
-      for (i = 0; i < width; ++i) {
-       for (kk = 0; kk < nComps; ++kk) {
-         if (inBits < nBits) {
-           inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
-           inBits += 8;
-         }
-         upLeftBuf[kk] = (upLeftBuf[kk] +
-                          (inBuf >> (inBits - nBits))) & bitMask;
-         inBits -= nBits;
-         outBuf = (outBuf << nBits) | upLeftBuf[kk];
-         outBits += nBits;
-         if (outBits >= 8) {
-           predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
-           outBits -= 8;
-         }
-       }
-      }
-      if (outBits > 0) {
-       predLine[k++] = (Guchar)((outBuf << (8 - outBits)) +
-                                (inBuf & ((1 << (8 - outBits)) - 1)));
-      }
-    }
-  }
-
-  // reset to start of line
-  predIdx = pixBytes;
-
-  return gTrue;
-}
-
-//------------------------------------------------------------------------
-// FileStream
-//------------------------------------------------------------------------
-
-FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
-                      Guint lengthA, Object *dictA):
-    BaseStream(dictA) {
-  f = fA;
-  start = startA;
-  limited = limitedA;
-  length = lengthA;
-  bufPtr = bufEnd = buf;
-  bufPos = start;
-  savePos = 0;
-  saved = gFalse;
-}
-
-FileStream::~FileStream() {
-  close();
-}
-
-Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
-                                 Guint lengthA, Object *dictA) {
-  return new FileStream(f, startA, limitedA, lengthA, dictA);
-}
-
-void FileStream::reset() {
-#if HAVE_FSEEKO
-  savePos = (Guint)ftello(f);
-  fseeko(f, start, SEEK_SET);
-#elif HAVE_FSEEK64
-  savePos = (Guint)ftell64(f);
-  fseek64(f, start, SEEK_SET);
-#else
-  savePos = (Guint)ftell(f);
-  fseek(f, start, SEEK_SET);
-#endif
-  saved = gTrue;
-  bufPtr = bufEnd = buf;
-  bufPos = start;
-  if (decrypt)
-    decrypt->reset();
-}
-
-void FileStream::close() {
-  if (saved) {
-#if HAVE_FSEEKO
-    fseeko(f, savePos, SEEK_SET);
-#elif HAVE_FSEEK64
-    fseek64(f, savePos, SEEK_SET);
-#else
-    fseek(f, savePos, SEEK_SET);
-#endif
-    saved = gFalse;
-  }
-}
-
-GBool FileStream::fillBuf() {
-  int n;
-  char *p;
-
-  bufPos += bufEnd - buf;
-  bufPtr = bufEnd = buf;
-  if (limited && bufPos >= start + length) {
-    return gFalse;
-  }
-  if (limited && bufPos + fileStreamBufSize > start + length) {
-    n = start + length - bufPos;
-  } else {
-    n = fileStreamBufSize;
-  }
-  n = fread(buf, 1, n, f);
-  bufEnd = buf + n;
-  if (bufPtr >= bufEnd) {
-    return gFalse;
-  }
-  if (decrypt) {
-    for (p = buf; p < bufEnd; ++p) {
-      *p = (char)decrypt->decryptByte((Guchar)*p);
-    }
-  }
-  return gTrue;
-}
-
-void FileStream::setPos(Guint pos, int dir) {
-  Guint size;
-
-  if (dir >= 0) {
-#if HAVE_FSEEKO
-    fseeko(f, pos, SEEK_SET);
-#elif HAVE_FSEEK64
-    fseek64(f, pos, SEEK_SET);
-#else
-    fseek(f, pos, SEEK_SET);
-#endif
-    bufPos = pos;
-  } else {
-#if HAVE_FSEEKO
-    fseeko(f, 0, SEEK_END);
-    size = (Guint)ftello(f);
-#elif HAVE_FSEEK64
-    fseek64(f, 0, SEEK_END);
-    size = (Guint)ftell64(f);
-#else
-    fseek(f, 0, SEEK_END);
-    size = (Guint)ftell(f);
-#endif
-    if (pos > size)
-      pos = (Guint)size;
-#ifdef __CYGWIN32__
-    //~ work around a bug in cygwin's implementation of fseek
-    rewind(f);
-#endif
-#if HAVE_FSEEKO
-    fseeko(f, -(int)pos, SEEK_END);
-    bufPos = (Guint)ftello(f);
-#elif HAVE_FSEEK64
-    fseek64(f, -(int)pos, SEEK_END);
-    bufPos = (Guint)ftell64(f);
-#else
-    fseek(f, -(int)pos, SEEK_END);
-    bufPos = (Guint)ftell(f);
-#endif
-  }
-  bufPtr = bufEnd = buf;
-}
-
-void FileStream::moveStart(int delta) {
-  start += delta;
-  bufPtr = bufEnd = buf;
-  bufPos = start;
-}
-
-//------------------------------------------------------------------------
-// MemStream
-//------------------------------------------------------------------------
-
-MemStream::MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA):
-    BaseStream(dictA) {
-  buf = bufA;
-  start = startA;
-  length = lengthA;
-  bufEnd = buf + start + length;
-  bufPtr = buf + start;
-  needFree = gFalse;
-}
-
-MemStream::~MemStream() {
-  if (needFree) {
-    gfree(buf);
-  }
-}
-
-Stream *MemStream::makeSubStream(Guint startA, GBool limited,
-                                Guint lengthA, Object *dictA) {
-  MemStream *subStr;
-  Guint newLength;
-
-  if (!limited || startA + lengthA > start + length) {
-    newLength = start + length - startA;
-  } else {
-    newLength = lengthA;
-  }
-  subStr = new MemStream(buf, startA, newLength, dictA);
-  return subStr;
-}
-
-void MemStream::reset() {
-  bufPtr = buf + start;
-  if (decrypt) {
-    decrypt->reset();
-  }
-}
-
-void MemStream::close() {
-}
-
-void MemStream::setPos(Guint pos, int dir) {
-  Guint i;
-
-  if (dir >= 0) {
-    i = pos;
-  } else {
-    i = start + length - pos;
-  }
-  if (i < start) {
-    i = start;
-  } else if (i > start + length) {
-    i = start + length;
-  }
-  bufPtr = buf + i;
-}
-
-void MemStream::moveStart(int delta) {
-  start += delta;
-  length -= delta;
-  bufPtr = buf + start;
-}
-
-void MemStream::doDecryption(Guchar *fileKey, int keyLength,
-                            int objNum, int objGen) {
-  char *newBuf;
-  char *p, *q;
-
-  this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
-  if (decrypt) {
-    newBuf = (char *)gmalloc(length);
-    for (p = buf + start, q = newBuf; p < bufEnd; ++p, ++q) {
-      *q = (char)decrypt->decryptByte((Guchar)*p);
-    }
-    bufEnd = newBuf + length;
-    bufPtr = newBuf + (bufPtr - (buf + start));
-    start = 0;
-    buf = newBuf;
-    needFree = gTrue;
-  }
-}
-
-//------------------------------------------------------------------------
-// EmbedStream
-//------------------------------------------------------------------------
-
-EmbedStream::EmbedStream(Stream *strA, Object *dictA,
-                        GBool limitedA, Guint lengthA):
-    BaseStream(dictA) {
-  str = strA;
-  limited = limitedA;
-  length = lengthA;
-}
-
-EmbedStream::~EmbedStream() {
-}
-
-Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA,
-                                  Guint lengthA, Object *dictA) {
-  error(-1, "Internal: called makeSubStream() on EmbedStream");
-  return NULL;
-}
-
-int EmbedStream::getChar() {
-  if (limited && !length) {
-    return EOF;
-  }
-  --length;
-  return str->getChar();
-}
-
-int EmbedStream::lookChar() {
-  if (limited && !length) {
-    return EOF;
-  }
-  return str->lookChar();
-}
-
-void EmbedStream::setPos(Guint pos, int dir) {
-  error(-1, "Internal: called setPos() on EmbedStream");
-}
-
-Guint EmbedStream::getStart() {
-  error(-1, "Internal: called getStart() on EmbedStream");
-  return 0;
-}
-
-void EmbedStream::moveStart(int delta) {
-  error(-1, "Internal: called moveStart() on EmbedStream");
-}
-
-//------------------------------------------------------------------------
-// ASCIIHexStream
-//------------------------------------------------------------------------
-
-ASCIIHexStream::ASCIIHexStream(Stream *strA):
-    FilterStream(strA) {
-  buf = EOF;
-  eof = gFalse;
-}
-
-ASCIIHexStream::~ASCIIHexStream() {
-  delete str;
-}
-
-void ASCIIHexStream::reset() {
-  str->reset();
-  buf = EOF;
-  eof = gFalse;
-}
-
-int ASCIIHexStream::lookChar() {
-  int c1, c2, x;
-
-  if (buf != EOF)
-    return buf;
-  if (eof) {
-    buf = EOF;
-    return EOF;
-  }
-  do {
-    c1 = str->getChar();
-  } while (isspace(c1));
-  if (c1 == '>') {
-    eof = gTrue;
-    buf = EOF;
-    return buf;
-  }
-  do {
-    c2 = str->getChar();
-  } while (isspace(c2));
-  if (c2 == '>') {
-    eof = gTrue;
-    c2 = '0';
-  }
-  if (c1 >= '0' && c1 <= '9') {
-    x = (c1 - '0') << 4;
-  } else if (c1 >= 'A' && c1 <= 'F') {
-    x = (c1 - 'A' + 10) << 4;
-  } else if (c1 >= 'a' && c1 <= 'f') {
-    x = (c1 - 'a' + 10) << 4;
-  } else if (c1 == EOF) {
-    eof = gTrue;
-    x = 0;
-  } else {
-    error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
-    x = 0;
-  }
-  if (c2 >= '0' && c2 <= '9') {
-    x += c2 - '0';
-  } else if (c2 >= 'A' && c2 <= 'F') {
-    x += c2 - 'A' + 10;
-  } else if (c2 >= 'a' && c2 <= 'f') {
-    x += c2 - 'a' + 10;
-  } else if (c2 == EOF) {
-    eof = gTrue;
-    x = 0;
-  } else {
-    error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
-  }
-  buf = x & 0xff;
-  return buf;
-}
-
-GString *ASCIIHexStream::getPSFilter(int psLevel, char *indent) {
-  GString *s;
-
-  if (psLevel < 2) {
-    return NULL;
-  }
-  if (!(s = str->getPSFilter(psLevel, indent))) {
-    return NULL;
-  }
-  s->append(indent)->append("/ASCIIHexDecode filter\n");
-  return s;
-}
-
-GBool ASCIIHexStream::isBinary(GBool last) {
-  return str->isBinary(gFalse);
-}
-
-//------------------------------------------------------------------------
-// ASCII85Stream
-//------------------------------------------------------------------------
-
-ASCII85Stream::ASCII85Stream(Stream *strA):
-    FilterStream(strA) {
-  index = n = 0;
-  eof = gFalse;
-}
-
-ASCII85Stream::~ASCII85Stream() {
-  delete str;
-}
-
-void ASCII85Stream::reset() {
-  str->reset();
-  index = n = 0;
-  eof = gFalse;
-}
-
-int ASCII85Stream::lookChar() {
-  int k;
-  Gulong t;
-
-  if (index >= n) {
-    if (eof)
-      return EOF;
-    index = 0;
-    do {
-      c[0] = str->getChar();
-    } while (Lexer::isSpace(c[0]));
-    if (c[0] == '~' || c[0] == EOF) {
-      eof = gTrue;
-      n = 0;
-      return EOF;
-    } else if (c[0] == 'z') {
-      b[0] = b[1] = b[2] = b[3] = 0;
-      n = 4;
-    } else {
-      for (k = 1; k < 5; ++k) {
-       do {
-         c[k] = str->getChar();
-       } while (Lexer::isSpace(c[k]));
-       if (c[k] == '~' || c[k] == EOF)
-         break;
-      }
-      n = k - 1;
-      if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
-       for (++k; k < 5; ++k)
-         c[k] = 0x21 + 84;
-       eof = gTrue;
-      }
-      t = 0;
-      for (k = 0; k < 5; ++k)
-       t = t * 85 + (c[k] - 0x21);
-      for (k = 3; k >= 0; --k) {
-       b[k] = (int)(t & 0xff);
-       t >>= 8;
-      }
-    }
-  }
-  return b[index];
-}
-
-GString *ASCII85Stream::getPSFilter(int psLevel, char *indent) {
-  GString *s;
-
-  if (psLevel < 2) {
-    return NULL;
-  }
-  if (!(s = str->getPSFilter(psLevel, indent))) {
-    return NULL;
-  }
-  s->append(indent)->append("/ASCII85Decode filter\n");
-  return s;
-}
-
-GBool ASCII85Stream::isBinary(GBool last) {
-  return str->isBinary(gFalse);
-}
-
-//------------------------------------------------------------------------
-// LZWStream
-//------------------------------------------------------------------------
-
-LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
-                    int bits, int earlyA):
-    FilterStream(strA) {
-  if (predictor != 1) {
-    pred = new StreamPredictor(this, predictor, columns, colors, bits);
-    if (!pred->isOk()) {
-      delete pred;
-      pred = NULL;
-    }
-  } else {
-    pred = NULL;
-  }
-  early = earlyA;
-  eof = gFalse;
-  inputBits = 0;
-  clearTable();
-}
-
-LZWStream::~LZWStream() {
-  if (pred) {
-    delete pred;
-  }
-  delete str;
-}
-
-int LZWStream::getChar() {
-  if (pred) {
-    return pred->getChar();
-  }
-  if (eof) {
-    return EOF;
-  }
-  if (seqIndex >= seqLength) {
-    if (!processNextCode()) {
-      return EOF;
-    }
-  }
-  return seqBuf[seqIndex++];
-}
-
-int LZWStream::lookChar() {
-  if (pred) {
-    return pred->lookChar();
-  }
-  if (eof) {
-    return EOF;
-  }
-  if (seqIndex >= seqLength) {
-    if (!processNextCode()) {
-      return EOF;
-    }
-  }
-  return seqBuf[seqIndex];
-}
-
-int LZWStream::getRawChar() {
-  if (eof) {
-    return EOF;
-  }
-  if (seqIndex >= seqLength) {
-    if (!processNextCode()) {
-      return EOF;
-    }
-  }
-  return seqBuf[seqIndex++];
-}
-
-void LZWStream::reset() {
-  str->reset();
-  eof = gFalse;
-  inputBits = 0;
-  clearTable();
-}
-
-GBool LZWStream::processNextCode() {
-  int code;
-  int nextLength;
-  int i, j;
-
-  // check for EOF
-  if (eof) {
-    return gFalse;
-  }
-
-  // check for eod and clear-table codes
- start:
-  code = getCode();
-  if (code == EOF || code == 257) {
-    eof = gTrue;
-    return gFalse;
-  }
-  if (code == 256) {
-    clearTable();
-    goto start;
-  }
-  if (nextCode >= 4097) {
-    error(getPos(), "Bad LZW stream - expected clear-table code");
-    clearTable();
-  }
-
-  // process the next code
-  nextLength = seqLength + 1;
-  if (code < 256) {
-    seqBuf[0] = code;
-    seqLength = 1;
-  } else if (code < nextCode) {
-    seqLength = table[code].length;
-    for (i = seqLength - 1, j = code; i > 0; --i) {
-      seqBuf[i] = table[j].tail;
-      j = table[j].head;
-    }
-    seqBuf[0] = j;
-  } else if (code == nextCode) {
-    seqBuf[seqLength] = newChar;
-    ++seqLength;
-  } else {
-    error(getPos(), "Bad LZW stream - unexpected code");
-    eof = gTrue;
-    return gFalse;
-  }
-  newChar = seqBuf[0];
-  if (first) {
-    first = gFalse;
-  } else {
-    table[nextCode].length = nextLength;
-    table[nextCode].head = prevCode;
-    table[nextCode].tail = newChar;
-    ++nextCode;
-    if (nextCode + early == 512)
-      nextBits = 10;
-    else if (nextCode + early == 1024)
-      nextBits = 11;
-    else if (nextCode + early == 2048)
-      nextBits = 12;
-  }
-  prevCode = code;
-
-  // reset buffer
-  seqIndex = 0;
-
-  return gTrue;
-}
-
-void LZWStream::clearTable() {
-  nextCode = 258;
-  nextBits = 9;
-  seqIndex = seqLength = 0;
-  first = gTrue;
-}
-
-int LZWStream::getCode() {
-  int c;
-  int code;
-
-  while (inputBits < nextBits) {
-    if ((c = str->getChar()) == EOF)
-      return EOF;
-    inputBuf = (inputBuf << 8) | (c & 0xff);
-    inputBits += 8;
-  }
-  code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
-  inputBits -= nextBits;
-  return code;
-}
-
-GString *LZWStream::getPSFilter(int psLevel, char *indent) {
-  GString *s;
-
-  if (psLevel < 2 || pred) {
-    return NULL;
-  }
-  if (!(s = str->getPSFilter(psLevel, indent))) {
-    return NULL;
-  }
-  s->append(indent)->append("<< ");
-  if (!early) {
-    s->append("/EarlyChange 0 ");
-  }
-  s->append(">> /LZWDecode filter\n");
-  return s;
-}
-
-GBool LZWStream::isBinary(GBool last) {
-  return str->isBinary(gTrue);
-}
-
-//------------------------------------------------------------------------
-// RunLengthStream
-//------------------------------------------------------------------------
-
-RunLengthStream::RunLengthStream(Stream *strA):
-    FilterStream(strA) {
-  bufPtr = bufEnd = buf;
-  eof = gFalse;
-}
-
-RunLengthStream::~RunLengthStream() {
-  delete str;
-}
-
-void RunLengthStream::reset() {
-  str->reset();
-  bufPtr = bufEnd = buf;
-  eof = gFalse;
-}
-
-GString *RunLengthStream::getPSFilter(int psLevel, char *indent) {
-  GString *s;
-
-  if (psLevel < 2) {
-    return NULL;
-  }
-  if (!(s = str->getPSFilter(psLevel, indent))) {
-    return NULL;
-  }
-  s->append(indent)->append("/RunLengthDecode filter\n");
-  return s;
-}
-
-GBool RunLengthStream::isBinary(GBool last) {
-  return str->isBinary(gTrue);
-}
-
-GBool RunLengthStream::fillBuf() {
-  int c;
-  int n, i;
-
-  if (eof)
-    return gFalse;
-  c = str->getChar();
-  if (c == 0x80 || c == EOF) {
-    eof = gTrue;
-    return gFalse;
-  }
-  if (c < 0x80) {
-    n = c + 1;
-    for (i = 0; i < n; ++i)
-      buf[i] = (char)str->getChar();
-  } else {
-    n = 0x101 - c;
-    c = str->getChar();
-    for (i = 0; i < n; ++i)
-      buf[i] = (char)c;
-  }
-  bufPtr = buf;
-  bufEnd = buf + n;
-  return gTrue;
-}
-
-//------------------------------------------------------------------------
-// CCITTFaxStream
-//------------------------------------------------------------------------
-
-CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
-                              GBool byteAlignA, int columnsA, int rowsA,
-                              GBool endOfBlockA, GBool blackA):
-    FilterStream(strA) {
-  encoding = encodingA;
-  endOfLine = endOfLineA;
-  byteAlign = byteAlignA;
-  columns = columnsA;
-  if (columns < 1) {
-    columns = 1;
-  }
-  rows = rowsA;
-  endOfBlock = endOfBlockA;
-  black = blackA;
-  refLine = (short *)gmallocn(columns + 4, sizeof(short));
-  codingLine = (short *)gmallocn(columns + 3, sizeof(short));
-
-  eof = gFalse;
-  row = 0;
-  nextLine2D = encoding < 0;
-  inputBits = 0;
-  codingLine[0] = 0;
-  codingLine[1] = refLine[2] = columns;
-  a0 = 1;
-
-  buf = EOF;
-}
-
-CCITTFaxStream::~CCITTFaxStream() {
-  delete str;
-  gfree(refLine);
-  gfree(codingLine);
-}
-
-void CCITTFaxStream::reset() {
-  short code1;
-
-  str->reset();
-  eof = gFalse;
-  row = 0;
-  nextLine2D = encoding < 0;
-  inputBits = 0;
-  codingLine[0] = 0;
-  codingLine[1] = refLine[2] = columns;
-  a0 = 1;
-  buf = EOF;
-
-  // skip any initial zero bits and end-of-line marker, and get the 2D
-  // encoding tag
-  while ((code1 = lookBits(12)) == 0) {
-    eatBits(1);
-  }
-  if (code1 == 0x001) {
-    eatBits(12);
-  }
-  if (encoding > 0) {
-    nextLine2D = !lookBits(1);
-    eatBits(1);
-  }
-}
-
-int CCITTFaxStream::lookChar() {
-  short code1, code2, code3;
-  int a0New;
-  GBool err, gotEOL;
-  int ret;
-  int bits, i;
-
-  // if at eof just return EOF
-  if (eof && codingLine[a0] >= columns) {
-    return EOF;
-  }
-
-  // read the next row
-  err = gFalse;
-  if (codingLine[a0] >= columns) {
-
-    // 2-D encoding
-    if (nextLine2D) {
-      for (i = 0; codingLine[i] < columns; ++i)
-       refLine[i] = codingLine[i];
-      refLine[i] = refLine[i + 1] = columns;
-      b1 = 1;
-      a0New = codingLine[a0 = 0] = 0;
-      do {
-       code1 = getTwoDimCode();
-       switch (code1) {
-       case twoDimPass:
-         if (refLine[b1] < columns) {
-           a0New = refLine[b1 + 1];
-           b1 += 2;
-         }
-         break;
-       case twoDimHoriz:
-         if ((a0 & 1) == 0) {
-           code1 = code2 = 0;
-           do {
-             code1 += code3 = getWhiteCode();
-           } while (code3 >= 64);
-           do {
-             code2 += code3 = getBlackCode();
-           } while (code3 >= 64);
-         } else {
-           code1 = code2 = 0;
-           do {
-             code1 += code3 = getBlackCode();
-           } while (code3 >= 64);
-           do {
-             code2 += code3 = getWhiteCode();
-           } while (code3 >= 64);
-         }
-         if (code1 > 0 || code2 > 0) {
-           codingLine[a0 + 1] = a0New + code1;
-           ++a0;
-           a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
-           ++a0;
-           while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
-             b1 += 2;
-         }
-         break;
-       case twoDimVert0:
-         a0New = codingLine[++a0] = refLine[b1];
-         if (refLine[b1] < columns) {
-           ++b1;
-           while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
-             b1 += 2;
-         }
-         break;
-       case twoDimVertR1:
-         a0New = codingLine[++a0] = refLine[b1] + 1;
-         if (refLine[b1] < columns) {
-           ++b1;
-           while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
-             b1 += 2;
-         }
-         break;
-       case twoDimVertL1:
-         if (a0 == 0 || refLine[b1] - 1 > a0New) {
-           a0New = codingLine[++a0] = refLine[b1] - 1;
-           --b1;
-           while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
-             b1 += 2;
-         }
-         break;
-       case twoDimVertR2:
-         a0New = codingLine[++a0] = refLine[b1] + 2;
-         if (refLine[b1] < columns) {
-           ++b1;
-           while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
-             b1 += 2;
-         }
-         break;
-       case twoDimVertL2:
-         if (a0 == 0 || refLine[b1] - 2 > a0New) {
-           a0New = codingLine[++a0] = refLine[b1] - 2;
-           --b1;
-           while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
-             b1 += 2;
-         }
-         break;
-       case twoDimVertR3:
-         a0New = codingLine[++a0] = refLine[b1] + 3;
-         if (refLine[b1] < columns) {
-           ++b1;
-           while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
-             b1 += 2;
-         }
-         break;
-       case twoDimVertL3:
-         if (a0 == 0 || refLine[b1] - 3 > a0New) {
-           a0New = codingLine[++a0] = refLine[b1] - 3;
-           --b1;
-           while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
-             b1 += 2;
-         }
-         break;
-       case EOF:
-         eof = gTrue;
-         codingLine[a0 = 0] = columns;
-         return EOF;
-       default:
-         error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
-         err = gTrue;
-         break;
-       }
-      } while (codingLine[a0] < columns);
-
-    // 1-D encoding
-    } else {
-      codingLine[a0 = 0] = 0;
-      while (1) {
-       code1 = 0;
-       do {
-         code1 += code3 = getWhiteCode();
-       } while (code3 >= 64);
-       codingLine[a0+1] = codingLine[a0] + code1;
-       ++a0;
-       if (codingLine[a0] >= columns)
-         break;
-       code2 = 0;
-       do {
-         code2 += code3 = getBlackCode();
-       } while (code3 >= 64);
-       codingLine[a0+1] = codingLine[a0] + code2;
-       ++a0;
-       if (codingLine[a0] >= columns)
-         break;
-      }
-    }
-
-    if (codingLine[a0] != columns) {
-      error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
-      // force the row to be the correct length
-      while (codingLine[a0] > columns) {
-       --a0;
-      }
-      codingLine[++a0] = columns;
-      err = gTrue;
-    }
-
-    // byte-align the row
-    if (byteAlign) {
-      inputBits &= ~7;
-    }
-
-    // check for end-of-line marker, skipping over any extra zero bits
-    gotEOL = gFalse;
-    if (!endOfBlock && row == rows - 1) {
-      eof = gTrue;
-    } else {
-      code1 = lookBits(12);
-      while (code1 == 0) {
-       eatBits(1);
-       code1 = lookBits(12);
-      }
-      if (code1 == 0x001) {
-       eatBits(12);
-       gotEOL = gTrue;
-      } else if (code1 == EOF) {
-       eof = gTrue;
-      }
-    }
-
-    // get 2D encoding tag
-    if (!eof && encoding > 0) {
-      nextLine2D = !lookBits(1);
-      eatBits(1);
-    }
-
-    // check for end-of-block marker
-    if (endOfBlock && gotEOL) {
-      code1 = lookBits(12);
-      if (code1 == 0x001) {
-       eatBits(12);
-       if (encoding > 0) {
-         lookBits(1);
-         eatBits(1);
-       }
-       if (encoding >= 0) {
-         for (i = 0; i < 4; ++i) {
-           code1 = lookBits(12);
-           if (code1 != 0x001) {
-             error(getPos(), "Bad RTC code in CCITTFax stream");
-           }
-           eatBits(12);
-           if (encoding > 0) {
-             lookBits(1);
-             eatBits(1);
-           }
-         }
-       }
-       eof = gTrue;
-      }
-
-    // look for an end-of-line marker after an error -- we only do
-    // this if we know the stream contains end-of-line markers because
-    // the "just plow on" technique tends to work better otherwise
-    } else if (err && endOfLine) {
-      do {
-       if (code1 == EOF) {
-         eof = gTrue;
-         return EOF;
-       }
-       eatBits(1);
-       code1 = lookBits(13);
-      } while ((code1 >> 1) != 0x001);
-      eatBits(12); 
-      if (encoding > 0) {
-       eatBits(1);
-       nextLine2D = !(code1 & 1);
-      }
-    }
-
-    a0 = 0;
-    outputBits = codingLine[1] - codingLine[0];
-    if (outputBits == 0) {
-      a0 = 1;
-      outputBits = codingLine[2] - codingLine[1];
-    }
-
-    ++row;
-  }
-
-  // get a byte
-  if (outputBits >= 8) {
-    ret = ((a0 & 1) == 0) ? 0xff : 0x00;
-    if ((outputBits -= 8) == 0) {
-      ++a0;
-      if (codingLine[a0] < columns) {
-       outputBits = codingLine[a0 + 1] - codingLine[a0];
-      }
-    }
-  } else {
-    bits = 8;
-    ret = 0;
-    do {
-      if (outputBits > bits) {
-       i = bits;
-       bits = 0;
-       if ((a0 & 1) == 0) {
-         ret |= 0xff >> (8 - i);
-       }
-       outputBits -= i;
-      } else {
-       i = outputBits;
-       bits -= outputBits;
-       if ((a0 & 1) == 0) {
-         ret |= (0xff >> (8 - i)) << bits;
-       }
-       outputBits = 0;
-       ++a0;
-       if (codingLine[a0] < columns) {
-         outputBits = codingLine[a0 + 1] - codingLine[a0];
-       }
-      }
-    } while (bits > 0 && codingLine[a0] < columns);
-  }
-  buf = black ? (ret ^ 0xff) : ret;
-  return buf;
-}
-
-short CCITTFaxStream::getTwoDimCode() {
-  short code;
-  CCITTCode *p;
-  int n;
-
-  code = 0; // make gcc happy
-  if (endOfBlock) {
-    code = lookBits(7);
-    p = &twoDimTab1[code];
-    if (p->bits > 0) {
-      eatBits(p->bits);
-      return p->n;
-    }
-  } else {
-    for (n = 1; n <= 7; ++n) {
-      code = lookBits(n);
-      if (n < 7) {
-       code <<= 7 - n;
-      }
-      p = &twoDimTab1[code];
-      if (p->bits == n) {
-       eatBits(n);
-       return p->n;
-      }
-    }
-  }
-  error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
-  return EOF;
-}
-
-short CCITTFaxStream::getWhiteCode() {
-  short code;
-  CCITTCode *p;
-  int n;
-
-  code = 0; // make gcc happy
-  if (endOfBlock) {
-    code = lookBits(12);
-    if ((code >> 5) == 0) {
-      p = &whiteTab1[code];
-    } else {
-      p = &whiteTab2[code >> 3];
-    }
-    if (p->bits > 0) {
-      eatBits(p->bits);
-      return p->n;
-    }
-  } else {
-    for (n = 1; n <= 9; ++n) {
-      code = lookBits(n);
-      if (n < 9) {
-       code <<= 9 - n;
-      }
-      p = &whiteTab2[code];
-      if (p->bits == n) {
-       eatBits(n);
-       return p->n;
-      }
-    }
-    for (n = 11; n <= 12; ++n) {
-      code = lookBits(n);
-      if (n < 12) {
-       code <<= 12 - n;
-      }
-      p = &whiteTab1[code];
-      if (p->bits == n) {
-       eatBits(n);
-       return p->n;
-      }
-    }
-  }
-  error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
-  // eat a bit and return a positive number so that the caller doesn't
-  // go into an infinite loop
-  eatBits(1);
-  return 1;
-}
-
-short CCITTFaxStream::getBlackCode() {
-  short code;
-  CCITTCode *p;
-  int n;
-
-  code = 0; // make gcc happy
-  if (endOfBlock) {
-    code = lookBits(13);
-    if ((code >> 7) == 0) {
-      p = &blackTab1[code];
-    } else if ((code >> 9) == 0) {
-      p = &blackTab2[(code >> 1) - 64];
-    } else {
-      p = &blackTab3[code >> 7];
-    }
-    if (p->bits > 0) {
-      eatBits(p->bits);
-      return p->n;
-    }
-  } else {
-    for (n = 2; n <= 6; ++n) {
-      code = lookBits(n);
-      if (n < 6) {
-       code <<= 6 - n;
-      }
-      p = &blackTab3[code];
-      if (p->bits == n) {
-       eatBits(n);
-       return p->n;
-      }
-    }
-    for (n = 7; n <= 12; ++n) {
-      code = lookBits(n);
-      if (n < 12) {
-       code <<= 12 - n;
-      }
-      if (code >= 64) {
-       p = &blackTab2[code - 64];
-       if (p->bits == n) {
-         eatBits(n);
-         return p->n;
-       }
-      }
-    }
-    for (n = 10; n <= 13; ++n) {
-      code = lookBits(n);
-      if (n < 13) {
-       code <<= 13 - n;
-      }
-      p = &blackTab1[code];
-      if (p->bits == n) {
-       eatBits(n);
-       return p->n;
-      }
-    }
-  }
-  error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
-  // eat a bit and return a positive number so that the caller doesn't
-  // go into an infinite loop
-  eatBits(1);
-  return 1;
-}
-
-short CCITTFaxStream::lookBits(int n) {
-  int c;
-
-  while (inputBits < n) {
-    if ((c = str->getChar()) == EOF) {
-      if (inputBits == 0) {
-       return EOF;
-      }
-      // near the end of the stream, the caller may ask for more bits
-      // than are available, but there may still be a valid code in
-      // however many bits are available -- we need to return correct
-      // data in this case
-      return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
-    }
-    inputBuf = (inputBuf << 8) + c;
-    inputBits += 8;
-  }
-  return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
-}
-
-GString *CCITTFaxStream::getPSFilter(int psLevel, char *indent) {
-  GString *s;
-  char s1[50];
-
-  if (psLevel < 2) {
-    return NULL;
-  }
-  if (!(s = str->getPSFilter(psLevel, indent))) {
-    return NULL;
-  }
-  s->append(indent)->append("<< ");
-  if (encoding != 0) {
-    sprintf(s1, "/K %d ", encoding);
-    s->append(s1);
-  }
-  if (endOfLine) {
-    s->append("/EndOfLine true ");
-  }
-  if (byteAlign) {
-    s->append("/EncodedByteAlign true ");
-  }
-  sprintf(s1, "/Columns %d ", columns);
-  s->append(s1);
-  if (rows != 0) {
-    sprintf(s1, "/Rows %d ", rows);
-    s->append(s1);
-  }
-  if (!endOfBlock) {
-    s->append("/EndOfBlock false ");
-  }
-  if (black) {
-    s->append("/BlackIs1 true ");
-  }
-  s->append(">> /CCITTFaxDecode filter\n");
-  return s;
-}
-
-GBool CCITTFaxStream::isBinary(GBool last) {
-  return str->isBinary(gTrue);
-}
-
-//------------------------------------------------------------------------
-// DCTStream
-//------------------------------------------------------------------------
-
-// IDCT constants (20.12 fixed point format)
-#define dctCos1    4017                // cos(pi/16)
-#define dctSin1     799                // sin(pi/16)
-#define dctCos3    3406                // cos(3*pi/16)
-#define dctSin3    2276                // sin(3*pi/16)
-#define dctCos6    1567                // cos(6*pi/16)
-#define dctSin6    3784                // sin(6*pi/16)
-#define dctSqrt2   5793                // sqrt(2)
-#define dctSqrt1d2 2896                // sqrt(2) / 2
-
-// color conversion parameters (16.16 fixed point format)
-#define dctCrToR   91881       //  1.4020
-#define dctCbToG  -22553       // -0.3441363
-#define dctCrToG  -46802       // -0.71413636
-#define dctCbToB  116130       //  1.772
-
-// clip [-256,511] --> [0,255]
-#define dctClipOffset 256
-static Guchar dctClip[768];
-static int dctClipInit = 0;
-
-// zig zag decode map
-static int dctZigZag[64] = {
-   0,
-   1,  8,
-  16,  9,  2,
-   3, 10, 17, 24,
-  32, 25, 18, 11, 4,
-   5, 12, 19, 26, 33, 40,
-  48, 41, 34, 27, 20, 13,  6,
-   7, 14, 21, 28, 35, 42, 49, 56,
-  57, 50, 43, 36, 29, 22, 15,
-  23, 30, 37, 44, 51, 58,
-  59, 52, 45, 38, 31,
-  39, 46, 53, 60,
-  61, 54, 47,
-  55, 62,
-  63
-};
-
-DCTStream::DCTStream(Stream *strA):
-    FilterStream(strA) {
-  int i, j;
-
-  progressive = interleaved = gFalse;
-  width = height = 0;
-  mcuWidth = mcuHeight = 0;
-  numComps = 0;
-  comp = 0;
-  x = y = dy = 0;
-  for (i = 0; i < 4; ++i) {
-    for (j = 0; j < 32; ++j) {
-      rowBuf[i][j] = NULL;
-    }
-    frameBuf[i] = NULL;
-  }
-
-  if (!dctClipInit) {
-    for (i = -256; i < 0; ++i)
-      dctClip[dctClipOffset + i] = 0;
-    for (i = 0; i < 256; ++i)
-      dctClip[dctClipOffset + i] = i;
-    for (i = 256; i < 512; ++i)
-      dctClip[dctClipOffset + i] = 255;
-    dctClipInit = 1;
-  }
-}
-
-DCTStream::~DCTStream() {
-  int i, j;
-
-  delete str;
-  if (progressive || !interleaved) {
-    for (i = 0; i < numComps; ++i) {
-      gfree(frameBuf[i]);
-    }
-  } else {
-    for (i = 0; i < numComps; ++i) {
-      for (j = 0; j < mcuHeight; ++j) {
-       gfree(rowBuf[i][j]);
-      }
-    }
-  }
-}
-
-void DCTStream::reset() {
-  int i, j;
-
-  str->reset();
-
-  progressive = interleaved = gFalse;
-  width = height = 0;
-  numComps = 0;
-  numQuantTables = 0;
-  numDCHuffTables = 0;
-  numACHuffTables = 0;
-  colorXform = 0;
-  gotJFIFMarker = gFalse;
-  gotAdobeMarker = gFalse;
-  restartInterval = 0;
-
-  if (!readHeader()) {
-    y = height;
-    return;
-  }
-
-  // compute MCU size
-  if (numComps == 1) {
-    compInfo[0].hSample = compInfo[0].vSample = 1;
-  }
-  mcuWidth = compInfo[0].hSample;
-  mcuHeight = compInfo[0].vSample;
-  for (i = 1; i < numComps; ++i) {
-    if (compInfo[i].hSample > mcuWidth) {
-      mcuWidth = compInfo[i].hSample;
-    }
-    if (compInfo[i].vSample > mcuHeight) {
-      mcuHeight = compInfo[i].vSample;
-    }
-  }
-  mcuWidth *= 8;
-  mcuHeight *= 8;
-
-  // figure out color transform
-  if (!gotAdobeMarker && numComps == 3) {
-    if (gotJFIFMarker) {
-      colorXform = 1;
-    } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
-              compInfo[2].id == 66) { // ASCII "RGB"
-      colorXform = 0;
-    } else {
-      colorXform = 1;
-    }
-  }
-
-  if (progressive || !interleaved) {
-
-    // allocate a buffer for the whole image
-    bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
-    bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
-    for (i = 0; i < numComps; ++i) {
-      frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int));
-      memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
-    }
-
-    // read the image data
-    do {
-      restartMarker = 0xd0;
-      restart();
-      readScan();
-    } while (readHeader());
-
-    // decode
-    decodeImage();
-
-    // initialize counters
-    comp = 0;
-    x = 0;
-    y = 0;
-
-  } else {
-
-    // allocate a buffer for one row of MCUs
-    bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
-    for (i = 0; i < numComps; ++i) {
-      for (j = 0; j < mcuHeight; ++j) {
-       rowBuf[i][j] = (Guchar *)gmallocn(bufWidth, sizeof(Guchar));
-      }
-    }
-
-    // initialize counters
-    comp = 0;
-    x = 0;
-    y = 0;
-    dy = mcuHeight;
-
-    restartMarker = 0xd0;
-    restart();
-  }
-}
-
-int DCTStream::getChar() {
-  int c;
-
-  if (y >= height) {
-    return EOF;
-  }
-  if (progressive || !interleaved) {
-    c = frameBuf[comp][y * bufWidth + x];
-    if (++comp == numComps) {
-      comp = 0;
-      if (++x == width) {
-       x = 0;
-       ++y;
-      }
-    }
-  } else {
-    if (dy >= mcuHeight) {
-      if (!readMCURow()) {
-       y = height;
-       return EOF;
-      }
-      comp = 0;
-      x = 0;
-      dy = 0;
-    }
-    c = rowBuf[comp][dy][x];
-    if (++comp == numComps) {
-      comp = 0;
-      if (++x == width) {
-       x = 0;
-       ++y;
-       ++dy;
-       if (y == height) {
-         readTrailer();
-       }
-      }
-    }
-  }
-  return c;
-}
-
-int DCTStream::lookChar() {
-  if (y >= height) {
-    return EOF;
-  }
-  if (progressive || !interleaved) {
-    return frameBuf[comp][y * bufWidth + x];
-  } else {
-    if (dy >= mcuHeight) {
-      if (!readMCURow()) {
-       y = height;
-       return EOF;
-      }
-      comp = 0;
-      x = 0;
-      dy = 0;
-    }
-    return rowBuf[comp][dy][x];
-  }
-}
-
-void DCTStream::restart() {
-  int i;
-
-  inputBits = 0;
-  restartCtr = restartInterval;
-  for (i = 0; i < numComps; ++i) {
-    compInfo[i].prevDC = 0;
-  }
-  eobRun = 0;
-}
-
-// Read one row of MCUs from a sequential JPEG stream.
-GBool DCTStream::readMCURow() {
-  int data1[64];
-  Guchar data2[64];
-  Guchar *p1, *p2;
-  int pY, pCb, pCr, pR, pG, pB;
-  int h, v, horiz, vert, hSub, vSub;
-  int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
-  int c;
-
-  for (x1 = 0; x1 < width; x1 += mcuWidth) {
-
-    // deal with restart marker
-    if (restartInterval > 0 && restartCtr == 0) {
-      c = readMarker();
-      if (c != restartMarker) {
-       error(getPos(), "Bad DCT data: incorrect restart marker");
-       return gFalse;
-      }
-      if (++restartMarker == 0xd8)
-       restartMarker = 0xd0;
-      restart();
-    }
-
-    // read one MCU
-    for (cc = 0; cc < numComps; ++cc) {
-      h = compInfo[cc].hSample;
-      v = compInfo[cc].vSample;
-      horiz = mcuWidth / h;
-      vert = mcuHeight / v;
-      hSub = horiz / 8;
-      vSub = vert / 8;
-      for (y2 = 0; y2 < mcuHeight; y2 += vert) {
-       for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
-         if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
-                           &acHuffTables[scanInfo.acHuffTable[cc]],
-                           &compInfo[cc].prevDC,
-                           data1)) {
-           return gFalse;
-         }
-         transformDataUnit(quantTables[compInfo[cc].quantTable],
-                           data1, data2);
-         if (hSub == 1 && vSub == 1) {
-           for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
-             p1 = &rowBuf[cc][y2+y3][x1+x2];
-             p1[0] = data2[i];
-             p1[1] = data2[i+1];
-             p1[2] = data2[i+2];
-             p1[3] = data2[i+3];
-             p1[4] = data2[i+4];
-             p1[5] = data2[i+5];
-             p1[6] = data2[i+6];
-             p1[7] = data2[i+7];
-           }
-         } else if (hSub == 2 && vSub == 2) {
-           for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
-             p1 = &rowBuf[cc][y2+y3][x1+x2];
-             p2 = &rowBuf[cc][y2+y3+1][x1+x2];
-             p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
-             p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
-             p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
-             p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
-             p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
-             p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
-             p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
-             p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
-           }
-         } else {
-           i = 0;
-           for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
-             for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
-               for (y5 = 0; y5 < vSub; ++y5)
-                 for (x5 = 0; x5 < hSub; ++x5)
-                   rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
-               ++i;
-             }
-           }
-         }
-       }
-      }
-    }
-    --restartCtr;
-
-    // color space conversion
-    if (colorXform) {
-      // convert YCbCr to RGB
-      if (numComps == 3) {
-       for (y2 = 0; y2 < mcuHeight; ++y2) {
-         for (x2 = 0; x2 < mcuWidth; ++x2) {
-           pY = rowBuf[0][y2][x1+x2];
-           pCb = rowBuf[1][y2][x1+x2] - 128;
-           pCr = rowBuf[2][y2][x1+x2] - 128;
-           pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
-           rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
-           pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
-           rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
-           pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
-           rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
-         }
-       }
-      // convert YCbCrK to CMYK (K is passed through unchanged)
-      } else if (numComps == 4) {
-       for (y2 = 0; y2 < mcuHeight; ++y2) {
-         for (x2 = 0; x2 < mcuWidth; ++x2) {
-           pY = rowBuf[0][y2][x1+x2];
-           pCb = rowBuf[1][y2][x1+x2] - 128;
-           pCr = rowBuf[2][y2][x1+x2] - 128;
-           pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
-           rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
-           pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
-           rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
-           pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
-           rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
-         }
-       }
-      }
-    }
-  }
-  return gTrue;
-}
-
-// Read one scan from a progressive or non-interleaved JPEG stream.
-void DCTStream::readScan() {
-  int data[64];
-  int x1, y1, dx1, dy1, x2, y2, y3, cc, i;
-  int h, v, horiz, vert, vSub;
-  int *p1;
-  int c;
-
-  if (scanInfo.numComps == 1) {
-    for (cc = 0; cc < numComps; ++cc) {
-      if (scanInfo.comp[cc]) {
-       break;
-      }
-    }
-    dx1 = mcuWidth / compInfo[cc].hSample;
-    dy1 = mcuHeight / compInfo[cc].vSample;
-  } else {
-    dx1 = mcuWidth;
-    dy1 = mcuHeight;
-  }
-
-  for (y1 = 0; y1 < height; y1 += dy1) {
-    for (x1 = 0; x1 < width; x1 += dx1) {
-
-      // deal with restart marker
-      if (restartInterval > 0 && restartCtr == 0) {
-       c = readMarker();
-       if (c != restartMarker) {
-         error(getPos(), "Bad DCT data: incorrect restart marker");
-         return;
-       }
-       if (++restartMarker == 0xd8) {
-         restartMarker = 0xd0;
-       }
-       restart();
-      }
-
-      // read one MCU
-      for (cc = 0; cc < numComps; ++cc) {
-       if (!scanInfo.comp[cc]) {
-         continue;
-       }
-
-       h = compInfo[cc].hSample;
-       v = compInfo[cc].vSample;
-       horiz = mcuWidth / h;
-       vert = mcuHeight / v;
-       vSub = vert / 8;
-       for (y2 = 0; y2 < dy1; y2 += vert) {
-         for (x2 = 0; x2 < dx1; x2 += horiz) {
-
-           // pull out the current values
-           p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
-           for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
-             data[i] = p1[0];
-             data[i+1] = p1[1];
-             data[i+2] = p1[2];
-             data[i+3] = p1[3];
-             data[i+4] = p1[4];
-             data[i+5] = p1[5];
-             data[i+6] = p1[6];
-             data[i+7] = p1[7];
-             p1 += bufWidth * vSub;
-           }
-
-           // read one data unit
-           if (progressive) {
-             if (!readProgressiveDataUnit(
-                      &dcHuffTables[scanInfo.dcHuffTable[cc]],
-                      &acHuffTables[scanInfo.acHuffTable[cc]],
-                      &compInfo[cc].prevDC,
-                      data)) {
-               return;
-             }
-           } else {
-             if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
-                               &acHuffTables[scanInfo.acHuffTable[cc]],
-                               &compInfo[cc].prevDC,
-                               data)) {
-               return;
-             }
-           }
-
-           // add the data unit into frameBuf
-           p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
-           for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
-             p1[0] = data[i];
-             p1[1] = data[i+1];
-             p1[2] = data[i+2];
-             p1[3] = data[i+3];
-             p1[4] = data[i+4];
-             p1[5] = data[i+5];
-             p1[6] = data[i+6];
-             p1[7] = data[i+7];
-             p1 += bufWidth * vSub;
-           }
-         }
-       }
-      }
-      --restartCtr;
-    }
-  }
-}
-
-// Read one data unit from a sequential JPEG stream.
-GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
-                             DCTHuffTable *acHuffTable,
-                             int *prevDC, int data[64]) {
-  int run, size, amp;
-  int c;
-  int i, j;
-
-  if ((size = readHuffSym(dcHuffTable)) == 9999) {
-    return gFalse;
-  }
-  if (size > 0) {
-    if ((amp = readAmp(size)) == 9999) {
-      return gFalse;
-    }
-  } else {
-    amp = 0;
-  }
-  data[0] = *prevDC += amp;
-  for (i = 1; i < 64; ++i) {
-    data[i] = 0;
-  }
-  i = 1;
-  while (i < 64) {
-    run = 0;
-    while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
-      run += 0x10;
-    }
-    if (c == 9999) {
-      return gFalse;
-    }
-    if (c == 0x00) {
-      break;
-    } else {
-      run += (c >> 4) & 0x0f;
-      size = c & 0x0f;
-      amp = readAmp(size);
-      if (amp == 9999) {
-       return gFalse;
-      }
-      i += run;
-      if (i < 64) {
-       j = dctZigZag[i++];
-       data[j] = amp;
-      }
-    }
-  }
-  return gTrue;
-}
-
-// Read one data unit from a sequential JPEG stream.
-GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
-                                        DCTHuffTable *acHuffTable,
-                                        int *prevDC, int data[64]) {
-  int run, size, amp, bit, c;
-  int i, j, k;
-
-  // get the DC coefficient
-  i = scanInfo.firstCoeff;
-  if (i == 0) {
-    if (scanInfo.ah == 0) {
-      if ((size = readHuffSym(dcHuffTable)) == 9999) {
-       return gFalse;
-      }
-      if (size > 0) {
-       if ((amp = readAmp(size)) == 9999) {
-         return gFalse;
-       }
-      } else {
-       amp = 0;
-      }
-      data[0] += (*prevDC += amp) << scanInfo.al;
-    } else {
-      if ((bit = readBit()) == 9999) {
-       return gFalse;
-      }
-      data[0] += bit << scanInfo.al;
-    }
-    ++i;
-  }
-  if (scanInfo.lastCoeff == 0) {
-    return gTrue;
-  }
-
-  // check for an EOB run
-  if (eobRun > 0) {
-    while (i <= scanInfo.lastCoeff) {
-      j = dctZigZag[i++];
-      if (data[j] != 0) {
-       if ((bit = readBit()) == EOF) {
-         return gFalse;
-       }
-       if (bit) {
-         data[j] += 1 << scanInfo.al;
-       }
-      }
-    }
-    --eobRun;
-    return gTrue;
-  }
-
-  // read the AC coefficients
-  while (i <= scanInfo.lastCoeff) {
-    if ((c = readHuffSym(acHuffTable)) == 9999) {
-      return gFalse;
-    }
-
-    // ZRL
-    if (c == 0xf0) {
-      k = 0;
-      while (k < 16) {
-       j = dctZigZag[i++];
-       if (data[j] == 0) {
-         ++k;
-       } else {
-         if ((bit = readBit()) == EOF) {
-           return gFalse;
-         }
-         if (bit) {
-           data[j] += 1 << scanInfo.al;
-         }
-       }
-      }
-
-    // EOB run
-    } else if ((c & 0x0f) == 0x00) {
-      j = c >> 4;
-      eobRun = 0;
-      for (k = 0; k < j; ++k) {
-       if ((bit = readBit()) == EOF) {
-         return gFalse;
-       }
-       eobRun = (eobRun << 1) | bit;
-      }
-      eobRun += 1 << j;
-      while (i <= scanInfo.lastCoeff) {
-       j = dctZigZag[i++];
-       if (data[j] != 0) {
-         if ((bit = readBit()) == EOF) {
-           return gFalse;
-         }
-         if (bit) {
-           data[j] += 1 << scanInfo.al;
-         }
-       }
-      }
-      --eobRun;
-      break;
-
-    // zero run and one AC coefficient
-    } else {
-      run = (c >> 4) & 0x0f;
-      size = c & 0x0f;
-      if ((amp = readAmp(size)) == 9999) {
-       return gFalse;
-      }
-      k = 0;
-      do {
-       j = dctZigZag[i++];
-       while (data[j] != 0) {
-         if ((bit = readBit()) == EOF) {
-           return gFalse;
-         }
-         if (bit) {
-           data[j] += 1 << scanInfo.al;
-         }
-         j = dctZigZag[i++];
-       }
-       ++k;
-      } while (k <= run);
-      data[j] = amp << scanInfo.al;
-    }
-  }
-
-  return gTrue;
-}
-
-// Decode a progressive JPEG image.
-void DCTStream::decodeImage() {
-  int dataIn[64];
-  Guchar dataOut[64];
-  Gushort *quantTable;
-  int pY, pCb, pCr, pR, pG, pB;
-  int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
-  int h, v, horiz, vert, hSub, vSub;
-  int *p0, *p1, *p2;
-
-  for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
-    for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
-      for (cc = 0; cc < numComps; ++cc) {
-       quantTable = quantTables[compInfo[cc].quantTable];
-       h = compInfo[cc].hSample;
-       v = compInfo[cc].vSample;
-       horiz = mcuWidth / h;
-       vert = mcuHeight / v;
-       hSub = horiz / 8;
-       vSub = vert / 8;
-       for (y2 = 0; y2 < mcuHeight; y2 += vert) {
-         for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
-
-           // pull out the coded data unit
-           p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
-           for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
-             dataIn[i]   = p1[0];
-             dataIn[i+1] = p1[1];
-             dataIn[i+2] = p1[2];
-             dataIn[i+3] = p1[3];
-             dataIn[i+4] = p1[4];
-             dataIn[i+5] = p1[5];
-             dataIn[i+6] = p1[6];
-             dataIn[i+7] = p1[7];
-             p1 += bufWidth * vSub;
-           }
-
-           // transform
-           transformDataUnit(quantTable, dataIn, dataOut);
-
-           // store back into frameBuf, doing replication for
-           // subsampled components
-           p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
-           if (hSub == 1 && vSub == 1) {
-             for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
-               p1[0] = dataOut[i] & 0xff;
-               p1[1] = dataOut[i+1] & 0xff;
-               p1[2] = dataOut[i+2] & 0xff;
-               p1[3] = dataOut[i+3] & 0xff;
-               p1[4] = dataOut[i+4] & 0xff;
-               p1[5] = dataOut[i+5] & 0xff;
-               p1[6] = dataOut[i+6] & 0xff;
-               p1[7] = dataOut[i+7] & 0xff;
-               p1 += bufWidth;
-             }
-           } else if (hSub == 2 && vSub == 2) {
-             p2 = p1 + bufWidth;
-             for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
-               p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
-               p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
-               p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
-               p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
-               p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
-               p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
-               p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
-               p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
-               p1 += bufWidth * 2;
-               p2 += bufWidth * 2;
-             }
-           } else {
-             i = 0;
-             for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
-               for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
-                 p2 = p1 + x4;
-                 for (y5 = 0; y5 < vSub; ++y5) {
-                   for (x5 = 0; x5 < hSub; ++x5) {
-                     p2[x5] = dataOut[i] & 0xff;
-                   }
-                   p2 += bufWidth;
-                 }
-                 ++i;
-               }
-               p1 += bufWidth * vSub;
-             }
-           }
-         }
-       }
-      }
-
-      // color space conversion
-      if (colorXform) {
-       // convert YCbCr to RGB
-       if (numComps == 3) {
-         for (y2 = 0; y2 < mcuHeight; ++y2) {
-           p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
-           p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
-           p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
-           for (x2 = 0; x2 < mcuWidth; ++x2) {
-             pY = *p0;
-             pCb = *p1 - 128;
-             pCr = *p2 - 128;
-             pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
-             *p0++ = dctClip[dctClipOffset + pR];
-             pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
-                   32768) >> 16;
-             *p1++ = dctClip[dctClipOffset + pG];
-             pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
-             *p2++ = dctClip[dctClipOffset + pB];
-           }
-         }
-       // convert YCbCrK to CMYK (K is passed through unchanged)
-       } else if (numComps == 4) {
-         for (y2 = 0; y2 < mcuHeight; ++y2) {
-           p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
-           p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
-           p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
-           for (x2 = 0; x2 < mcuWidth; ++x2) {
-             pY = *p0;
-             pCb = *p1 - 128;
-             pCr = *p2 - 128;
-             pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
-             *p0++ = 255 - dctClip[dctClipOffset + pR];
-             pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
-                   32768) >> 16;
-             *p1++ = 255 - dctClip[dctClipOffset + pG];
-             pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
-             *p2++ = 255 - dctClip[dctClipOffset + pB];
-           }
-         }
-       }
-      }
-    }
-  }
-}
-
-// Transform one data unit -- this performs the dequantization and
-// IDCT steps.  This IDCT algorithm is taken from:
-//   Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
-//   "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
-//   IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
-//   988-991.
-// The stage numbers mentioned in the comments refer to Figure 1 in this
-// paper.
-void DCTStream::transformDataUnit(Gushort *quantTable,
-                                 int dataIn[64], Guchar dataOut[64]) {
-  int v0, v1, v2, v3, v4, v5, v6, v7, t;
-  int *p;
-  int i;
-
-  // dequant
-  for (i = 0; i < 64; ++i) {
-    dataIn[i] *= quantTable[i];
-  }
-
-  // inverse DCT on rows
-  for (i = 0; i < 64; i += 8) {
-    p = dataIn + i;
-
-    // check for all-zero AC coefficients
-    if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
-       p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
-      t = (dctSqrt2 * p[0] + 512) >> 10;
-      p[0] = t;
-      p[1] = t;
-      p[2] = t;
-      p[3] = t;
-      p[4] = t;
-      p[5] = t;
-      p[6] = t;
-      p[7] = t;
-      continue;
-    }
-
-    // stage 4
-    v0 = (dctSqrt2 * p[0] + 128) >> 8;
-    v1 = (dctSqrt2 * p[4] + 128) >> 8;
-    v2 = p[2];
-    v3 = p[6];
-    v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
-    v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
-    v5 = p[3] << 4;
-    v6 = p[5] << 4;
-
-    // stage 3
-    t = (v0 - v1+ 1) >> 1;
-    v0 = (v0 + v1 + 1) >> 1;
-    v1 = t;
-    t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
-    v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
-    v3 = t;
-    t = (v4 - v6 + 1) >> 1;
-    v4 = (v4 + v6 + 1) >> 1;
-    v6 = t;
-    t = (v7 + v5 + 1) >> 1;
-    v5 = (v7 - v5 + 1) >> 1;
-    v7 = t;
-
-    // stage 2
-    t = (v0 - v3 + 1) >> 1;
-    v0 = (v0 + v3 + 1) >> 1;
-    v3 = t;
-    t = (v1 - v2 + 1) >> 1;
-    v1 = (v1 + v2 + 1) >> 1;
-    v2 = t;
-    t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
-    v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
-    v7 = t;
-    t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
-    v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
-    v6 = t;
-
-    // stage 1
-    p[0] = v0 + v7;
-    p[7] = v0 - v7;
-    p[1] = v1 + v6;
-    p[6] = v1 - v6;
-    p[2] = v2 + v5;
-    p[5] = v2 - v5;
-    p[3] = v3 + v4;
-    p[4] = v3 - v4;
-  }
-
-  // inverse DCT on columns
-  for (i = 0; i < 8; ++i) {
-    p = dataIn + i;
-
-    // check for all-zero AC coefficients
-    if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
-       p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
-      t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
-      p[0*8] = t;
-      p[1*8] = t;
-      p[2*8] = t;
-      p[3*8] = t;
-      p[4*8] = t;
-      p[5*8] = t;
-      p[6*8] = t;
-      p[7*8] = t;
-      continue;
-    }
-
-    // stage 4
-    v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
-    v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
-    v2 = p[2*8];
-    v3 = p[6*8];
-    v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
-    v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
-    v5 = p[3*8];
-    v6 = p[5*8];
-
-    // stage 3
-    t = (v0 - v1 + 1) >> 1;
-    v0 = (v0 + v1 + 1) >> 1;
-    v1 = t;
-    t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
-    v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
-    v3 = t;
-    t = (v4 - v6 + 1) >> 1;
-    v4 = (v4 + v6 + 1) >> 1;
-    v6 = t;
-    t = (v7 + v5 + 1) >> 1;
-    v5 = (v7 - v5 + 1) >> 1;
-    v7 = t;
-
-    // stage 2
-    t = (v0 - v3 + 1) >> 1;
-    v0 = (v0 + v3 + 1) >> 1;
-    v3 = t;
-    t = (v1 - v2 + 1) >> 1;
-    v1 = (v1 + v2 + 1) >> 1;
-    v2 = t;
-    t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
-    v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
-    v7 = t;
-    t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
-    v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
-    v6 = t;
-
-    // stage 1
-    p[0*8] = v0 + v7;
-    p[7*8] = v0 - v7;
-    p[1*8] = v1 + v6;
-    p[6*8] = v1 - v6;
-    p[2*8] = v2 + v5;
-    p[5*8] = v2 - v5;
-    p[3*8] = v3 + v4;
-    p[4*8] = v3 - v4;
-  }
-
-  // convert to 8-bit integers
-  for (i = 0; i < 64; ++i) {
-    dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
-  }
-}
-
-int DCTStream::readHuffSym(DCTHuffTable *table) {
-  Gushort code;
-  int bit;
-  int codeBits;
-
-  code = 0;
-  codeBits = 0;
-  do {
-    // add a bit to the code
-    if ((bit = readBit()) == EOF)
-      return 9999;
-    code = (code << 1) + bit;
-    ++codeBits;
-
-    // look up code
-    if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
-      code -= table->firstCode[codeBits];
-      return table->sym[table->firstSym[codeBits] + code];
-    }
-  } while (codeBits < 16);
-
-  error(getPos(), "Bad Huffman code in DCT stream");
-  return 9999;
-}
-
-int DCTStream::readAmp(int size) {
-  int amp, bit;
-  int bits;
-
-  amp = 0;
-  for (bits = 0; bits < size; ++bits) {
-    if ((bit = readBit()) == EOF)
-      return 9999;
-    amp = (amp << 1) + bit;
-  }
-  if (amp < (1 << (size - 1)))
-    amp -= (1 << size) - 1;
-  return amp;
-}
-
-int DCTStream::readBit() {
-  int bit;
-  int c, c2;
-
-  if (inputBits == 0) {
-    if ((c = str->getChar()) == EOF)
-      return EOF;
-    if (c == 0xff) {
-      do {
-       c2 = str->getChar();
-      } while (c2 == 0xff);
-      if (c2 != 0x00) {
-       error(getPos(), "Bad DCT data: missing 00 after ff");
-       return EOF;
-      }
-    }
-    inputBuf = c;
-    inputBits = 8;
-  }
-  bit = (inputBuf >> (inputBits - 1)) & 1;
-  --inputBits;
-  return bit;
-}
-
-GBool DCTStream::readHeader() {
-  GBool doScan;
-  int n;
-  int c = 0;
-  int i;
-
-  // read headers
-  doScan = gFalse;
-  while (!doScan) {
-    c = readMarker();
-    switch (c) {
-    case 0xc0:                 // SOF0 (sequential)
-    case 0xc1:                 // SOF1 (extended sequential)
-      if (!readBaselineSOF()) {
-       return gFalse;
-      }
-      break;
-    case 0xc2:                 // SOF2 (progressive)
-      if (!readProgressiveSOF()) {
-       return gFalse;
-      }
-      break;
-    case 0xc4:                 // DHT
-      if (!readHuffmanTables()) {
-       return gFalse;
-      }
-      break;
-    case 0xd8:                 // SOI
-      break;
-    case 0xd9:                 // EOI
-      return gFalse;
-    case 0xda:                 // SOS
-      if (!readScanInfo()) {
-       return gFalse;
-      }
-      doScan = gTrue;
-      break;
-    case 0xdb:                 // DQT
-      if (!readQuantTables()) {
-       return gFalse;
-      }
-      break;
-    case 0xdd:                 // DRI
-      if (!readRestartInterval()) {
-       return gFalse;
-      }
-      break;
-    case 0xe0:                 // APP0
-      if (!readJFIFMarker()) {
-       return gFalse;
-      }
-      break;
-    case 0xee:                 // APP14
-      if (!readAdobeMarker()) {
-       return gFalse;
-      }
-      break;
-    case EOF:
-      error(getPos(), "Bad DCT header");
-      return gFalse;
-    default:
-      // skip APPn / COM / etc.
-      if (c >= 0xe0) {
-       n = read16() - 2;
-       for (i = 0; i < n; ++i) {
-         str->getChar();
-       }
-      } else {
-       error(getPos(), "Unknown DCT marker <%02x>", c);
-       return gFalse;
-      }
-      break;
-    }
-  }
-
-  return gTrue;
-}
-
-GBool DCTStream::readBaselineSOF() {
-  int length;
-  int prec;
-  int i;
-  int c;
-
-  length = read16();
-  prec = str->getChar();
-  height = read16();
-  width = read16();
-  numComps = str->getChar();
-  if (numComps <= 0 || numComps > 4) {
-    error(getPos(), "Bad number of components in DCT stream", prec);
-    return gFalse;
-  }
-  if (numComps <= 0 || numComps > 4) {
-    error(getPos(), "Bad number of components in DCT stream", prec);
-    return gFalse;
-  }
-  if (prec != 8) {
-    error(getPos(), "Bad DCT precision %d", prec);
-    return gFalse;
-  }
-  for (i = 0; i < numComps; ++i) {
-    compInfo[i].id = str->getChar();
-    c = str->getChar();
-    compInfo[i].hSample = (c >> 4) & 0x0f;
-    compInfo[i].vSample = c & 0x0f;
-    compInfo[i].quantTable = str->getChar();
-  }
-  progressive = gFalse;
-  return gTrue;
-}
-
-GBool DCTStream::readProgressiveSOF() {
-  int length;
-  int prec;
-  int i;
-  int c;
-
-  length = read16();
-  prec = str->getChar();
-  height = read16();
-  width = read16();
-  numComps = str->getChar();
-  if (prec != 8) {
-    error(getPos(), "Bad DCT precision %d", prec);
-    return gFalse;
-  }
-  for (i = 0; i < numComps; ++i) {
-    compInfo[i].id = str->getChar();
-    c = str->getChar();
-    compInfo[i].hSample = (c >> 4) & 0x0f;
-    compInfo[i].vSample = c & 0x0f;
-    compInfo[i].quantTable = str->getChar();
-  }
-  progressive = gTrue;
-  return gTrue;
-}
-
-GBool DCTStream::readScanInfo() {
-  int length;
-  int id, c;
-  int i, j;
-
-  length = read16() - 2;
-  scanInfo.numComps = str->getChar();
-  --length;
-  if (length != 2 * scanInfo.numComps + 3) {
-    error(getPos(), "Bad DCT scan info block");
-    return gFalse;
-  }
-  interleaved = scanInfo.numComps == numComps;
-  for (j = 0; j < numComps; ++j) {
-    scanInfo.comp[j] = gFalse;
-  }
-  for (i = 0; i < scanInfo.numComps; ++i) {
-    id = str->getChar();
-    // some (broken) DCT streams reuse ID numbers, but at least they
-    // keep the components in order, so we check compInfo[i] first to
-    // work around the problem
-    if (id == compInfo[i].id) {
-      j = i;
-    } else {
-      for (j = 0; j < numComps; ++j) {
-       if (id == compInfo[j].id) {
-         break;
-       }
-      }
-      if (j == numComps) {
-       error(getPos(), "Bad DCT component ID in scan info block");
-       return gFalse;
-      }
-    }
-    scanInfo.comp[j] = gTrue;
-    c = str->getChar();
-    scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
-    scanInfo.acHuffTable[j] = c & 0x0f;
-  }
-  scanInfo.firstCoeff = str->getChar();
-  scanInfo.lastCoeff = str->getChar();
-  c = str->getChar();
-  scanInfo.ah = (c >> 4) & 0x0f;
-  scanInfo.al = c & 0x0f;
-  return gTrue;
-}
-
-GBool DCTStream::readQuantTables() {
-  int length, prec, i, index;
-
-  length = read16() - 2;
-  while (length > 0) {
-    index = str->getChar();
-    prec = (index >> 4) & 0x0f;
-    index &= 0x0f;
-    if (prec > 1 || index >= 4) {
-      error(getPos(), "Bad DCT quantization table");
-      return gFalse;
-    }
-    if (index == numQuantTables) {
-      numQuantTables = index + 1;
-    }
-    for (i = 0; i < 64; ++i) {
-      if (prec) {
-       quantTables[index][dctZigZag[i]] = read16();
-      } else {
-       quantTables[index][dctZigZag[i]] = str->getChar();
-      }
-    }
-    if (prec) {
-      length -= 129;
-    } else {
-      length -= 65;
-    }
-  }
-  return gTrue;
-}
-
-GBool DCTStream::readHuffmanTables() {
-  DCTHuffTable *tbl;
-  int length;
-  int index;
-  Gushort code;
-  Guchar sym;
-  int i;
-  int c;
-
-  length = read16() - 2;
-  while (length > 0) {
-    index = str->getChar();
-    --length;
-    if ((index & 0x0f) >= 4) {
-      error(getPos(), "Bad DCT Huffman table");
-      return gFalse;
-    }
-    if (index & 0x10) {
-      index &= 0x0f;
-      if (index >= numACHuffTables)
-       numACHuffTables = index+1;
-      tbl = &acHuffTables[index];
-    } else {
-      if (index >= numDCHuffTables)
-       numDCHuffTables = index+1;
-      tbl = &dcHuffTables[index];
-    }
-    sym = 0;
-    code = 0;
-    for (i = 1; i <= 16; ++i) {
-      c = str->getChar();
-      tbl->firstSym[i] = sym;
-      tbl->firstCode[i] = code;
-      tbl->numCodes[i] = c;
-      sym += c;
-      code = (code + c) << 1;
-    }
-    length -= 16;
-    for (i = 0; i < sym; ++i)
-      tbl->sym[i] = str->getChar();
-    length -= sym;
-  }
-  return gTrue;
-}
-
-GBool DCTStream::readRestartInterval() {
-  int length;
-
-  length = read16();
-  if (length != 4) {
-    error(getPos(), "Bad DCT restart interval");
-    return gFalse;
-  }
-  restartInterval = read16();
-  return gTrue;
-}
-
-GBool DCTStream::readJFIFMarker() {
-  int length, i;
-  char buf[5];
-  int c;
-
-  length = read16();
-  length -= 2;
-  if (length >= 5) {
-    for (i = 0; i < 5; ++i) {
-      if ((c = str->getChar()) == EOF) {
-       error(getPos(), "Bad DCT APP0 marker");
-       return gFalse;
-      }
-      buf[i] = c;
-    }
-    length -= 5;
-    if (!memcmp(buf, "JFIF\0", 5)) {
-      gotJFIFMarker = gTrue;
-    }
-  }
-  while (length > 0) {
-    if (str->getChar() == EOF) {
-      error(getPos(), "Bad DCT APP0 marker");
-      return gFalse;
-    }
-    --length;
-  }
-  return gTrue;
-}
-
-GBool DCTStream::readAdobeMarker() {
-  int length, i;
-  char buf[12];
-  int c;
-
-  length = read16();
-  if (length < 14) {
-    goto err;
-  }
-  for (i = 0; i < 12; ++i) {
-    if ((c = str->getChar()) == EOF) {
-      goto err;
-    }
-    buf[i] = c;
-  }
-  if (strncmp(buf, "Adobe", 5)) {
-    goto err;
-  }
-  colorXform = buf[11];
-  gotAdobeMarker = gTrue;
-  for (i = 14; i < length; ++i) {
-    if (str->getChar() == EOF) {
-      goto err;
-    }
-  }
-  return gTrue;
-
- err:
-  error(getPos(), "Bad DCT Adobe APP14 marker");
-  return gFalse;
-}
-
-GBool DCTStream::readTrailer() {
-  int c;
-
-  c = readMarker();
-  if (c != 0xd9) {             // EOI
-    error(getPos(), "Bad DCT trailer");
-    return gFalse;
-  }
-  return gTrue;
-}
-
-int DCTStream::readMarker() {
-  int c;
-
-  do {
-    do {
-      c = str->getChar();
-    } while (c != 0xff && c != EOF);
-    do {
-      c = str->getChar();
-    } while (c == 0xff);
-  } while (c == 0x00);
-  return c;
-}
-
-int DCTStream::read16() {
-  int c1, c2;
-
-  if ((c1 = str->getChar()) == EOF)
-    return EOF;
-  if ((c2 = str->getChar()) == EOF)
-    return EOF;
-  return (c1 << 8) + c2;
-}
-
-GString *DCTStream::getPSFilter(int psLevel, char *indent) {
-  GString *s;
-
-  if (psLevel < 2) {
-    return NULL;
-  }
-  if (!(s = str->getPSFilter(psLevel, indent))) {
-    return NULL;
-  }
-  s->append(indent)->append("<< >> /DCTDecode filter\n");
-  return s;
-}
-
-GBool DCTStream::isBinary(GBool last) {
-  return str->isBinary(gTrue);
-}
-
-//------------------------------------------------------------------------
-// FlateStream
-//------------------------------------------------------------------------
-
-int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
-  16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
-};
-
-FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
-  {0,   3},
-  {0,   4},
-  {0,   5},
-  {0,   6},
-  {0,   7},
-  {0,   8},
-  {0,   9},
-  {0,  10},
-  {1,  11},
-  {1,  13},
-  {1,  15},
-  {1,  17},
-  {2,  19},
-  {2,  23},
-  {2,  27},
-  {2,  31},
-  {3,  35},
-  {3,  43},
-  {3,  51},
-  {3,  59},
-  {4,  67},
-  {4,  83},
-  {4,  99},
-  {4, 115},
-  {5, 131},
-  {5, 163},
-  {5, 195},
-  {5, 227},
-  {0, 258},
-  {0, 258},
-  {0, 258}
-};
-
-FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
-  { 0,     1},
-  { 0,     2},
-  { 0,     3},
-  { 0,     4},
-  { 1,     5},
-  { 1,     7},
-  { 2,     9},
-  { 2,    13},
-  { 3,    17},
-  { 3,    25},
-  { 4,    33},
-  { 4,    49},
-  { 5,    65},
-  { 5,    97},
-  { 6,   129},
-  { 6,   193},
-  { 7,   257},
-  { 7,   385},
-  { 8,   513},
-  { 8,   769},
-  { 9,  1025},
-  { 9,  1537},
-  {10,  2049},
-  {10,  3073},
-  {11,  4097},
-  {11,  6145},
-  {12,  8193},
-  {12, 12289},
-  {13, 16385},
-  {13, 24577}
-};
-
-static FlateCode flateFixedLitCodeTabCodes[512] = {
-  {7, 0x0100},
-  {8, 0x0050},
-  {8, 0x0010},
-  {8, 0x0118},
-  {7, 0x0110},
-  {8, 0x0070},
-  {8, 0x0030},
-  {9, 0x00c0},
-  {7, 0x0108},
-  {8, 0x0060},
-  {8, 0x0020},
-  {9, 0x00a0},
-  {8, 0x0000},
-  {8, 0x0080},
-  {8, 0x0040},
-  {9, 0x00e0},
-  {7, 0x0104},
-  {8, 0x0058},
-  {8, 0x0018},
-  {9, 0x0090},
-  {7, 0x0114},
-  {8, 0x0078},
-  {8, 0x0038},
-  {9, 0x00d0},
-  {7, 0x010c},
-  {8, 0x0068},
-  {8, 0x0028},
-  {9, 0x00b0},
-  {8, 0x0008},
-  {8, 0x0088},
-  {8, 0x0048},
-  {9, 0x00f0},
-  {7, 0x0102},
-  {8, 0x0054},
-  {8, 0x0014},
-  {8, 0x011c},
-  {7, 0x0112},
-  {8, 0x0074},
-  {8, 0x0034},
-  {9, 0x00c8},
-  {7, 0x010a},
-  {8, 0x0064},
-  {8, 0x0024},
-  {9, 0x00a8},
-  {8, 0x0004},
-  {8, 0x0084},
-  {8, 0x0044},
-  {9, 0x00e8},
-  {7, 0x0106},
-  {8, 0x005c},
-  {8, 0x001c},
-  {9, 0x0098},
-  {7, 0x0116},
-  {8, 0x007c},
-  {8, 0x003c},
-  {9, 0x00d8},
-  {7, 0x010e},
-  {8, 0x006c},
-  {8, 0x002c},
-  {9, 0x00b8},
-  {8, 0x000c},
-  {8, 0x008c},
-  {8, 0x004c},
-  {9, 0x00f8},
-  {7, 0x0101},
-  {8, 0x0052},
-  {8, 0x0012},
-  {8, 0x011a},
-  {7, 0x0111},
-  {8, 0x0072},
-  {8, 0x0032},
-  {9, 0x00c4},
-  {7, 0x0109},
-  {8, 0x0062},
-  {8, 0x0022},
-  {9, 0x00a4},
-  {8, 0x0002},
-  {8, 0x0082},
-  {8, 0x0042},
-  {9, 0x00e4},
-  {7, 0x0105},
-  {8, 0x005a},
-  {8, 0x001a},
-  {9, 0x0094},
-  {7, 0x0115},
-  {8, 0x007a},
-  {8, 0x003a},
-  {9, 0x00d4},
-  {7, 0x010d},
-  {8, 0x006a},
-  {8, 0x002a},
-  {9, 0x00b4},
-  {8, 0x000a},
-  {8, 0x008a},
-  {8, 0x004a},
-  {9, 0x00f4},
-  {7, 0x0103},
-  {8, 0x0056},
-  {8, 0x0016},
-  {8, 0x011e},
-  {7, 0x0113},
-  {8, 0x0076},
-  {8, 0x0036},
-  {9, 0x00cc},
-  {7, 0x010b},
-  {8, 0x0066},
-  {8, 0x0026},
-  {9, 0x00ac},
-  {8, 0x0006},
-  {8, 0x0086},
-  {8, 0x0046},
-  {9, 0x00ec},
-  {7, 0x0107},
-  {8, 0x005e},
-  {8, 0x001e},
-  {9, 0x009c},
-  {7, 0x0117},
-  {8, 0x007e},
-  {8, 0x003e},
-  {9, 0x00dc},
-  {7, 0x010f},
-  {8, 0x006e},
-  {8, 0x002e},
-  {9, 0x00bc},
-  {8, 0x000e},
-  {8, 0x008e},
-  {8, 0x004e},
-  {9, 0x00fc},
-  {7, 0x0100},
-  {8, 0x0051},
-  {8, 0x0011},
-  {8, 0x0119},
-  {7, 0x0110},
-  {8, 0x0071},
-  {8, 0x0031},
-  {9, 0x00c2},
-  {7, 0x0108},
-  {8, 0x0061},
-  {8, 0x0021},
-  {9, 0x00a2},
-  {8, 0x0001},
-  {8, 0x0081},
-  {8, 0x0041},
-  {9, 0x00e2},
-  {7, 0x0104},
-  {8, 0x0059},
-  {8, 0x0019},
-  {9, 0x0092},
-  {7, 0x0114},
-  {8, 0x0079},
-  {8, 0x0039},
-  {9, 0x00d2},
-  {7, 0x010c},
-  {8, 0x0069},
-  {8, 0x0029},
-  {9, 0x00b2},
-  {8, 0x0009},
-  {8, 0x0089},
-  {8, 0x0049},
-  {9, 0x00f2},
-  {7, 0x0102},
-  {8, 0x0055},
-  {8, 0x0015},
-  {8, 0x011d},
-  {7, 0x0112},
-  {8, 0x0075},
-  {8, 0x0035},
-  {9, 0x00ca},
-  {7, 0x010a},
-  {8, 0x0065},
-  {8, 0x0025},
-  {9, 0x00aa},
-  {8, 0x0005},
-  {8, 0x0085},
-  {8, 0x0045},
-  {9, 0x00ea},
-  {7, 0x0106},
-  {8, 0x005d},
-  {8, 0x001d},
-  {9, 0x009a},
-  {7, 0x0116},
-  {8, 0x007d},
-  {8, 0x003d},
-  {9, 0x00da},
-  {7, 0x010e},
-  {8, 0x006d},
-  {8, 0x002d},
-  {9, 0x00ba},
-  {8, 0x000d},
-  {8, 0x008d},
-  {8, 0x004d},
-  {9, 0x00fa},
-  {7, 0x0101},
-  {8, 0x0053},
-  {8, 0x0013},
-  {8, 0x011b},
-  {7, 0x0111},
-  {8, 0x0073},
-  {8, 0x0033},
-  {9, 0x00c6},
-  {7, 0x0109},
-  {8, 0x0063},
-  {8, 0x0023},
-  {9, 0x00a6},
-  {8, 0x0003},
-  {8, 0x0083},
-  {8, 0x0043},
-  {9, 0x00e6},
-  {7, 0x0105},
-  {8, 0x005b},
-  {8, 0x001b},
-  {9, 0x0096},
-  {7, 0x0115},
-  {8, 0x007b},
-  {8, 0x003b},
-  {9, 0x00d6},
-  {7, 0x010d},
-  {8, 0x006b},
-  {8, 0x002b},
-  {9, 0x00b6},
-  {8, 0x000b},
-  {8, 0x008b},
-  {8, 0x004b},
-  {9, 0x00f6},
-  {7, 0x0103},
-  {8, 0x0057},
-  {8, 0x0017},
-  {8, 0x011f},
-  {7, 0x0113},
-  {8, 0x0077},
-  {8, 0x0037},
-  {9, 0x00ce},
-  {7, 0x010b},
-  {8, 0x0067},
-  {8, 0x0027},
-  {9, 0x00ae},
-  {8, 0x0007},
-  {8, 0x0087},
-  {8, 0x0047},
-  {9, 0x00ee},
-  {7, 0x0107},
-  {8, 0x005f},
-  {8, 0x001f},
-  {9, 0x009e},
-  {7, 0x0117},
-  {8, 0x007f},
-  {8, 0x003f},
-  {9, 0x00de},
-  {7, 0x010f},
-  {8, 0x006f},
-  {8, 0x002f},
-  {9, 0x00be},
-  {8, 0x000f},
-  {8, 0x008f},
-  {8, 0x004f},
-  {9, 0x00fe},
-  {7, 0x0100},
-  {8, 0x0050},
-  {8, 0x0010},
-  {8, 0x0118},
-  {7, 0x0110},
-  {8, 0x0070},
-  {8, 0x0030},
-  {9, 0x00c1},
-  {7, 0x0108},
-  {8, 0x0060},
-  {8, 0x0020},
-  {9, 0x00a1},
-  {8, 0x0000},
-  {8, 0x0080},
-  {8, 0x0040},
-  {9, 0x00e1},
-  {7, 0x0104},
-  {8, 0x0058},
-  {8, 0x0018},
-  {9, 0x0091},
-  {7, 0x0114},
-  {8, 0x0078},
-  {8, 0x0038},
-  {9, 0x00d1},
-  {7, 0x010c},
-  {8, 0x0068},
-  {8, 0x0028},
-  {9, 0x00b1},
-  {8, 0x0008},
-  {8, 0x0088},
-  {8, 0x0048},
-  {9, 0x00f1},
-  {7, 0x0102},
-  {8, 0x0054},
-  {8, 0x0014},
-  {8, 0x011c},
-  {7, 0x0112},
-  {8, 0x0074},
-  {8, 0x0034},
-  {9, 0x00c9},
-  {7, 0x010a},
-  {8, 0x0064},
-  {8, 0x0024},
-  {9, 0x00a9},
-  {8, 0x0004},
-  {8, 0x0084},
-  {8, 0x0044},
-  {9, 0x00e9},
-  {7, 0x0106},
-  {8, 0x005c},
-  {8, 0x001c},
-  {9, 0x0099},
-  {7, 0x0116},
-  {8, 0x007c},
-  {8, 0x003c},
-  {9, 0x00d9},
-  {7, 0x010e},
-  {8, 0x006c},
-  {8, 0x002c},
-  {9, 0x00b9},
-  {8, 0x000c},
-  {8, 0x008c},
-  {8, 0x004c},
-  {9, 0x00f9},
-  {7, 0x0101},
-  {8, 0x0052},
-  {8, 0x0012},
-  {8, 0x011a},
-  {7, 0x0111},
-  {8, 0x0072},
-  {8, 0x0032},
-  {9, 0x00c5},
-  {7, 0x0109},
-  {8, 0x0062},
-  {8, 0x0022},
-  {9, 0x00a5},
-  {8, 0x0002},
-  {8, 0x0082},
-  {8, 0x0042},
-  {9, 0x00e5},
-  {7, 0x0105},
-  {8, 0x005a},
-  {8, 0x001a},
-  {9, 0x0095},
-  {7, 0x0115},
-  {8, 0x007a},
-  {8, 0x003a},
-  {9, 0x00d5},
-  {7, 0x010d},
-  {8, 0x006a},
-  {8, 0x002a},
-  {9, 0x00b5},
-  {8, 0x000a},
-  {8, 0x008a},
-  {8, 0x004a},
-  {9, 0x00f5},
-  {7, 0x0103},
-  {8, 0x0056},
-  {8, 0x0016},
-  {8, 0x011e},
-  {7, 0x0113},
-  {8, 0x0076},
-  {8, 0x0036},
-  {9, 0x00cd},
-  {7, 0x010b},
-  {8, 0x0066},
-  {8, 0x0026},
-  {9, 0x00ad},
-  {8, 0x0006},
-  {8, 0x0086},
-  {8, 0x0046},
-  {9, 0x00ed},
-  {7, 0x0107},
-  {8, 0x005e},
-  {8, 0x001e},
-  {9, 0x009d},
-  {7, 0x0117},
-  {8, 0x007e},
-  {8, 0x003e},
-  {9, 0x00dd},
-  {7, 0x010f},
-  {8, 0x006e},
-  {8, 0x002e},
-  {9, 0x00bd},
-  {8, 0x000e},
-  {8, 0x008e},
-  {8, 0x004e},
-  {9, 0x00fd},
-  {7, 0x0100},
-  {8, 0x0051},
-  {8, 0x0011},
-  {8, 0x0119},
-  {7, 0x0110},
-  {8, 0x0071},
-  {8, 0x0031},
-  {9, 0x00c3},
-  {7, 0x0108},
-  {8, 0x0061},
-  {8, 0x0021},
-  {9, 0x00a3},
-  {8, 0x0001},
-  {8, 0x0081},
-  {8, 0x0041},
-  {9, 0x00e3},
-  {7, 0x0104},
-  {8, 0x0059},
-  {8, 0x0019},
-  {9, 0x0093},
-  {7, 0x0114},
-  {8, 0x0079},
-  {8, 0x0039},
-  {9, 0x00d3},
-  {7, 0x010c},
-  {8, 0x0069},
-  {8, 0x0029},
-  {9, 0x00b3},
-  {8, 0x0009},
-  {8, 0x0089},
-  {8, 0x0049},
-  {9, 0x00f3},
-  {7, 0x0102},
-  {8, 0x0055},
-  {8, 0x0015},
-  {8, 0x011d},
-  {7, 0x0112},
-  {8, 0x0075},
-  {8, 0x0035},
-  {9, 0x00cb},
-  {7, 0x010a},
-  {8, 0x0065},
-  {8, 0x0025},
-  {9, 0x00ab},
-  {8, 0x0005},
-  {8, 0x0085},
-  {8, 0x0045},
-  {9, 0x00eb},
-  {7, 0x0106},
-  {8, 0x005d},
-  {8, 0x001d},
-  {9, 0x009b},
-  {7, 0x0116},
-  {8, 0x007d},
-  {8, 0x003d},
-  {9, 0x00db},
-  {7, 0x010e},
-  {8, 0x006d},
-  {8, 0x002d},
-  {9, 0x00bb},
-  {8, 0x000d},
-  {8, 0x008d},
-  {8, 0x004d},
-  {9, 0x00fb},
-  {7, 0x0101},
-  {8, 0x0053},
-  {8, 0x0013},
-  {8, 0x011b},
-  {7, 0x0111},
-  {8, 0x0073},
-  {8, 0x0033},
-  {9, 0x00c7},
-  {7, 0x0109},
-  {8, 0x0063},
-  {8, 0x0023},
-  {9, 0x00a7},
-  {8, 0x0003},
-  {8, 0x0083},
-  {8, 0x0043},
-  {9, 0x00e7},
-  {7, 0x0105},
-  {8, 0x005b},
-  {8, 0x001b},
-  {9, 0x0097},
-  {7, 0x0115},
-  {8, 0x007b},
-  {8, 0x003b},
-  {9, 0x00d7},
-  {7, 0x010d},
-  {8, 0x006b},
-  {8, 0x002b},
-  {9, 0x00b7},
-  {8, 0x000b},
-  {8, 0x008b},
-  {8, 0x004b},
-  {9, 0x00f7},
-  {7, 0x0103},
-  {8, 0x0057},
-  {8, 0x0017},
-  {8, 0x011f},
-  {7, 0x0113},
-  {8, 0x0077},
-  {8, 0x0037},
-  {9, 0x00cf},
-  {7, 0x010b},
-  {8, 0x0067},
-  {8, 0x0027},
-  {9, 0x00af},
-  {8, 0x0007},
-  {8, 0x0087},
-  {8, 0x0047},
-  {9, 0x00ef},
-  {7, 0x0107},
-  {8, 0x005f},
-  {8, 0x001f},
-  {9, 0x009f},
-  {7, 0x0117},
-  {8, 0x007f},
-  {8, 0x003f},
-  {9, 0x00df},
-  {7, 0x010f},
-  {8, 0x006f},
-  {8, 0x002f},
-  {9, 0x00bf},
-  {8, 0x000f},
-  {8, 0x008f},
-  {8, 0x004f},
-  {9, 0x00ff}
-};
-
-FlateHuffmanTab FlateStream::fixedLitCodeTab = {
-  flateFixedLitCodeTabCodes, 9
-};
-
-static FlateCode flateFixedDistCodeTabCodes[32] = {
-  {5, 0x0000},
-  {5, 0x0010},
-  {5, 0x0008},
-  {5, 0x0018},
-  {5, 0x0004},
-  {5, 0x0014},
-  {5, 0x000c},
-  {5, 0x001c},
-  {5, 0x0002},
-  {5, 0x0012},
-  {5, 0x000a},
-  {5, 0x001a},
-  {5, 0x0006},
-  {5, 0x0016},
-  {5, 0x000e},
-  {0, 0x0000},
-  {5, 0x0001},
-  {5, 0x0011},
-  {5, 0x0009},
-  {5, 0x0019},
-  {5, 0x0005},
-  {5, 0x0015},
-  {5, 0x000d},
-  {5, 0x001d},
-  {5, 0x0003},
-  {5, 0x0013},
-  {5, 0x000b},
-  {5, 0x001b},
-  {5, 0x0007},
-  {5, 0x0017},
-  {5, 0x000f},
-  {0, 0x0000}
-};
-
-FlateHuffmanTab FlateStream::fixedDistCodeTab = {
-  flateFixedDistCodeTabCodes, 5
-};
-
-FlateStream::FlateStream(Stream *strA, int predictor, int columns,
-                        int colors, int bits):
-    FilterStream(strA) {
-  if (predictor != 1) {
-    pred = new StreamPredictor(this, predictor, columns, colors, bits);
-    if (!pred->isOk()) {
-      delete pred;
-      pred = NULL;
-    }
-  } else {
-    pred = NULL;
-  }
-  litCodeTab.codes = NULL;
-  distCodeTab.codes = NULL;
-}
-
-FlateStream::~FlateStream() {
-  if (litCodeTab.codes != fixedLitCodeTab.codes) {
-    gfree(litCodeTab.codes);
-  }
-  if (distCodeTab.codes != fixedDistCodeTab.codes) {
-    gfree(distCodeTab.codes);
-  }
-  if (pred) {
-    delete pred;
-  }
-  delete str;
-}
-
-void FlateStream::reset() {
-  int cmf, flg;
-
-  index = 0;
-  remain = 0;
-  codeBuf = 0;
-  codeSize = 0;
-  compressedBlock = gFalse;
-  endOfBlock = gTrue;
-  eof = gTrue;
-
-  str->reset();
-
-  // read header
-  //~ need to look at window size?
-  endOfBlock = eof = gTrue;
-  cmf = str->getChar();
-  flg = str->getChar();
-  if (cmf == EOF || flg == EOF)
-    return;
-  if ((cmf & 0x0f) != 0x08) {
-    error(getPos(), "Unknown compression method in flate stream");
-    return;
-  }
-  if ((((cmf << 8) + flg) % 31) != 0) {
-    error(getPos(), "Bad FCHECK in flate stream");
-    return;
-  }
-  if (flg & 0x20) {
-    error(getPos(), "FDICT bit set in flate stream");
-    return;
-  }
-
-  eof = gFalse;
-}
-
-int FlateStream::getChar() {
-  int c;
-
-  if (pred) {
-    return pred->getChar();
-  }
-  while (remain == 0) {
-    if (endOfBlock && eof)
-      return EOF;
-    readSome();
-  }
-  c = buf[index];
-  index = (index + 1) & flateMask;
-  --remain;
-  return c;
-}
-
-int FlateStream::lookChar() {
-  int c;
-
-  if (pred) {
-    return pred->lookChar();
-  }
-  while (remain == 0) {
-    if (endOfBlock && eof)
-      return EOF;
-    readSome();
-  }
-  c = buf[index];
-  return c;
-}
-
-int FlateStream::getRawChar() {
-  int c;
-
-  while (remain == 0) {
-    if (endOfBlock && eof)
-      return EOF;
-    readSome();
-  }
-  c = buf[index];
-  index = (index + 1) & flateMask;
-  --remain;
-  return c;
-}
-
-GString *FlateStream::getPSFilter(int psLevel, char *indent) {
-  GString *s;
-
-  if (psLevel < 3 || pred) {
-    return NULL;
-  }
-  if (!(s = str->getPSFilter(psLevel, indent))) {
-    return NULL;
-  }
-  s->append(indent)->append("<< >> /FlateDecode filter\n");
-  return s;
-}
-
-GBool FlateStream::isBinary(GBool last) {
-  return str->isBinary(gTrue);
-}
-
-void FlateStream::readSome() {
-  int code1, code2;
-  int len, dist;
-  int i, j, k;
-  int c;
-
-  if (endOfBlock) {
-    if (!startBlock())
-      return;
-  }
-
-  if (compressedBlock) {
-    if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
-      goto err;
-    if (code1 < 256) {
-      buf[index] = code1;
-      remain = 1;
-    } else if (code1 == 256) {
-      endOfBlock = gTrue;
-      remain = 0;
-    } else {
-      code1 -= 257;
-      code2 = lengthDecode[code1].bits;
-      if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
-       goto err;
-      len = lengthDecode[code1].first + code2;
-      if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
-       goto err;
-      code2 = distDecode[code1].bits;
-      if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
-       goto err;
-      dist = distDecode[code1].first + code2;
-      i = index;
-      j = (index - dist) & flateMask;
-      for (k = 0; k < len; ++k) {
-       buf[i] = buf[j];
-       i = (i + 1) & flateMask;
-       j = (j + 1) & flateMask;
-      }
-      remain = len;
-    }
-
-  } else {
-    len = (blockLen < flateWindow) ? blockLen : flateWindow;
-    for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
-      if ((c = str->getChar()) == EOF) {
-       endOfBlock = eof = gTrue;
-       break;
-      }
-      buf[j] = c & 0xff;
-    }
-    remain = i;
-    blockLen -= len;
-    if (blockLen == 0)
-      endOfBlock = gTrue;
-  }
-
-  return;
-
-err:
-  error(getPos(), "Unexpected end of file in flate stream");
-  endOfBlock = eof = gTrue;
-  remain = 0;
-}
-
-GBool FlateStream::startBlock() {
-  int blockHdr;
-  int c;
-  int check;
-
-  // free the code tables from the previous block
-  if (litCodeTab.codes != fixedLitCodeTab.codes) {
-    gfree(litCodeTab.codes);
-  }
-  litCodeTab.codes = NULL;
-  if (distCodeTab.codes != fixedDistCodeTab.codes) {
-    gfree(distCodeTab.codes);
-  }
-  distCodeTab.codes = NULL;
-
-  // read block header
-  blockHdr = getCodeWord(3);
-  if (blockHdr & 1)
-    eof = gTrue;
-  blockHdr >>= 1;
-
-  // uncompressed block
-  if (blockHdr == 0) {
-    compressedBlock = gFalse;
-    if ((c = str->getChar()) == EOF)
-      goto err;
-    blockLen = c & 0xff;
-    if ((c = str->getChar()) == EOF)
-      goto err;
-    blockLen |= (c & 0xff) << 8;
-    if ((c = str->getChar()) == EOF)
-      goto err;
-    check = c & 0xff;
-    if ((c = str->getChar()) == EOF)
-      goto err;
-    check |= (c & 0xff) << 8;
-    if (check != (~blockLen & 0xffff))
-      error(getPos(), "Bad uncompressed block length in flate stream");
-    codeBuf = 0;
-    codeSize = 0;
-
-  // compressed block with fixed codes
-  } else if (blockHdr == 1) {
-    compressedBlock = gTrue;
-    loadFixedCodes();
-
-  // compressed block with dynamic codes
-  } else if (blockHdr == 2) {
-    compressedBlock = gTrue;
-    if (!readDynamicCodes()) {
-      goto err;
-    }
-
-  // unknown block type
-  } else {
-    goto err;
-  }
-
-  endOfBlock = gFalse;
-  return gTrue;
-
-err:
-  error(getPos(), "Bad block header in flate stream");
-  endOfBlock = eof = gTrue;
-  return gFalse;
-}
-
-void FlateStream::loadFixedCodes() {
-  litCodeTab.codes = fixedLitCodeTab.codes;
-  litCodeTab.maxLen = fixedLitCodeTab.maxLen;
-  distCodeTab.codes = fixedDistCodeTab.codes;
-  distCodeTab.maxLen = fixedDistCodeTab.maxLen;
-}
-
-GBool FlateStream::readDynamicCodes() {
-  int numCodeLenCodes;
-  int numLitCodes;
-  int numDistCodes;
-  int codeLenCodeLengths[flateMaxCodeLenCodes];
-  FlateHuffmanTab codeLenCodeTab;
-  int len, repeat, code;
-  int i;
-
-  codeLenCodeTab.codes = NULL;
-
-  // read lengths
-  if ((numLitCodes = getCodeWord(5)) == EOF) {
-    goto err;
-  }
-  numLitCodes += 257;
-  if ((numDistCodes = getCodeWord(5)) == EOF) {
-    goto err;
-  }
-  numDistCodes += 1;
-  if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
-    goto err;
-  }
-  numCodeLenCodes += 4;
-  if (numLitCodes > flateMaxLitCodes ||
-      numDistCodes > flateMaxDistCodes ||
-      numCodeLenCodes > flateMaxCodeLenCodes) {
-    goto err;
-  }
-
-  // build the code length code table
-  for (i = 0; i < flateMaxCodeLenCodes; ++i) {
-    codeLenCodeLengths[i] = 0;
-  }
-  for (i = 0; i < numCodeLenCodes; ++i) {
-    if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
-      goto err;
-    }
-  }
-  compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
-
-  // build the literal and distance code tables
-  len = 0;
-  repeat = 0;
-  i = 0;
-  while (i < numLitCodes + numDistCodes) {
-    if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
-      goto err;
-    }
-    if (code == 16) {
-      if ((repeat = getCodeWord(2)) == EOF) {
-       goto err;
-      }
-      repeat += 3;
-      if (i + repeat > numLitCodes + numDistCodes) {
-       goto err;
-      }
-      for (; repeat > 0; --repeat) {
-       codeLengths[i++] = len;
-      }
-    } else if (code == 17) {
-      if ((repeat = getCodeWord(3)) == EOF) {
-       goto err;
-      }
-      repeat += 3;
-      if (i + repeat > numLitCodes + numDistCodes) {
-       goto err;
-      }
-      len = 0;
-      for (; repeat > 0; --repeat) {
-       codeLengths[i++] = 0;
-      }
-    } else if (code == 18) {
-      if ((repeat = getCodeWord(7)) == EOF) {
-       goto err;
-      }
-      repeat += 11;
-      if (i + repeat > numLitCodes + numDistCodes) {
-       goto err;
-      }
-      len = 0;
-      for (; repeat > 0; --repeat) {
-       codeLengths[i++] = 0;
-      }
-    } else {
-      codeLengths[i++] = len = code;
-    }
-  }
-  compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
-  compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
-
-  gfree(codeLenCodeTab.codes);
-  return gTrue;
-
-err:
-  error(getPos(), "Bad dynamic code table in flate stream");
-  gfree(codeLenCodeTab.codes);
-  return gFalse;
-}
-
-// Convert an array <lengths> of <n> lengths, in value order, into a
-// Huffman code lookup table.
-void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
-  int tabSize, len, code, code2, skip, val, i, t;
-
-  // find max code length
-  tab->maxLen = 0;
-  for (val = 0; val < n; ++val) {
-    if (lengths[val] > tab->maxLen) {
-      tab->maxLen = lengths[val];
-    }
-  }
-
-  // allocate the table
-  tabSize = 1 << tab->maxLen;
-  tab->codes = (FlateCode *)gmallocn(tabSize, sizeof(FlateCode));
-
-  // clear the table
-  for (i = 0; i < tabSize; ++i) {
-    tab->codes[i].len = 0;
-    tab->codes[i].val = 0;
-  }
-
-  // build the table
-  for (len = 1, code = 0, skip = 2;
-       len <= tab->maxLen;
-       ++len, code <<= 1, skip <<= 1) {
-    for (val = 0; val < n; ++val) {
-      if (lengths[val] == len) {
-
-       // bit-reverse the code
-       code2 = 0;
-       t = code;
-       for (i = 0; i < len; ++i) {
-         code2 = (code2 << 1) | (t & 1);
-         t >>= 1;
-       }
-
-       // fill in the table entries
-       for (i = code2; i < tabSize; i += skip) {
-         tab->codes[i].len = (Gushort)len;
-         tab->codes[i].val = (Gushort)val;
-       }
-
-       ++code;
-      }
-    }
-  }
-}
-
-int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
-  FlateCode *code;
-  int c;
-
-  while (codeSize < tab->maxLen) {
-    if ((c = str->getChar()) == EOF) {
-      break;
-    }
-    codeBuf |= (c & 0xff) << codeSize;
-    codeSize += 8;
-  }
-  code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
-  if (codeSize == 0 || codeSize < code->len || code->len == 0) {
-    return EOF;
-  }
-  codeBuf >>= code->len;
-  codeSize -= code->len;
-  return (int)code->val;
-}
-
-int FlateStream::getCodeWord(int bits) {
-  int c;
-
-  while (codeSize < bits) {
-    if ((c = str->getChar()) == EOF)
-      return EOF;
-    codeBuf |= (c & 0xff) << codeSize;
-    codeSize += 8;
-  }
-  c = codeBuf & ((1 << bits) - 1);
-  codeBuf >>= bits;
-  codeSize -= bits;
-  return c;
-}
-
-//------------------------------------------------------------------------
-// EOFStream
-//------------------------------------------------------------------------
-
-EOFStream::EOFStream(Stream *strA):
-    FilterStream(strA) {
-}
-
-EOFStream::~EOFStream() {
-  delete str;
-}
-
-//------------------------------------------------------------------------
-// FixedLengthEncoder
-//------------------------------------------------------------------------
-
-FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
-    FilterStream(strA) {
-  length = lengthA;
-  count = 0;
-}
-
-FixedLengthEncoder::~FixedLengthEncoder() {
-  if (str->isEncoder())
-    delete str;
-}
-
-void FixedLengthEncoder::reset() {
-  str->reset();
-  count = 0;
-}
-
-int FixedLengthEncoder::getChar() {
-  if (length >= 0 && count >= length)
-    return EOF;
-  ++count;
-  return str->getChar();
-}
-
-int FixedLengthEncoder::lookChar() {
-  if (length >= 0 && count >= length)
-    return EOF;
-  return str->getChar();
-}
-
-GBool FixedLengthEncoder::isBinary(GBool last) {
-  return str->isBinary(gTrue);
-}
-
-//------------------------------------------------------------------------
-// ASCIIHexEncoder
-//------------------------------------------------------------------------
-
-ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
-    FilterStream(strA) {
-  bufPtr = bufEnd = buf;
-  lineLen = 0;
-  eof = gFalse;
-}
-
-ASCIIHexEncoder::~ASCIIHexEncoder() {
-  if (str->isEncoder()) {
-    delete str;
-  }
-}
-
-void ASCIIHexEncoder::reset() {
-  str->reset();
-  bufPtr = bufEnd = buf;
-  lineLen = 0;
-  eof = gFalse;
-}
-
-GBool ASCIIHexEncoder::fillBuf() {
-  static char *hex = "0123456789abcdef";
-  int c;
-
-  if (eof) {
-    return gFalse;
-  }
-  bufPtr = bufEnd = buf;
-  if ((c = str->getChar()) == EOF) {
-    *bufEnd++ = '>';
-    eof = gTrue;
-  } else {
-    if (lineLen >= 64) {
-      *bufEnd++ = '\n';
-      lineLen = 0;
-    }
-    *bufEnd++ = hex[(c >> 4) & 0x0f];
-    *bufEnd++ = hex[c & 0x0f];
-    lineLen += 2;
-  }
-  return gTrue;
-}
-
-//------------------------------------------------------------------------
-// ASCII85Encoder
-//------------------------------------------------------------------------
-
-ASCII85Encoder::ASCII85Encoder(Stream *strA):
-    FilterStream(strA) {
-  bufPtr = bufEnd = buf;
-  lineLen = 0;
-  eof = gFalse;
-}
-
-ASCII85Encoder::~ASCII85Encoder() {
-  if (str->isEncoder())
-    delete str;
-}
-
-void ASCII85Encoder::reset() {
-  str->reset();
-  bufPtr = bufEnd = buf;
-  lineLen = 0;
-  eof = gFalse;
-}
-
-GBool ASCII85Encoder::fillBuf() {
-  Gulong t;
-  char buf1[5];
-  int c;
-  int n, i;
-
-  if (eof)
-    return gFalse;
-  t = 0;
-  for (n = 0; n < 4; ++n) {
-    if ((c = str->getChar()) == EOF)
-      break;
-    t = (t << 8) + c;
-  }
-  bufPtr = bufEnd = buf;
-  if (n > 0) {
-    if (n == 4 && t == 0) {
-      *bufEnd++ = 'z';
-      if (++lineLen == 65) {
-       *bufEnd++ = '\n';
-       lineLen = 0;
-      }
-    } else {
-      if (n < 4)
-       t <<= 8 * (4 - n);
-      for (i = 4; i >= 0; --i) {
-       buf1[i] = (char)(t % 85 + 0x21);
-       t /= 85;
-      }
-      for (i = 0; i <= n; ++i) {
-       *bufEnd++ = buf1[i];
-       if (++lineLen == 65) {
-         *bufEnd++ = '\n';
-         lineLen = 0;
-       }
-      }
-    }
-  }
-  if (n < 4) {
-    *bufEnd++ = '~';
-    *bufEnd++ = '>';
-    eof = gTrue;
-  }
-  return bufPtr < bufEnd;
-}
-
-//------------------------------------------------------------------------
-// RunLengthEncoder
-//------------------------------------------------------------------------
-
-RunLengthEncoder::RunLengthEncoder(Stream *strA):
-    FilterStream(strA) {
-  bufPtr = bufEnd = nextEnd = buf;
-  eof = gFalse;
-}
-
-RunLengthEncoder::~RunLengthEncoder() {
-  if (str->isEncoder())
-    delete str;
-}
-
-void RunLengthEncoder::reset() {
-  str->reset();
-  bufPtr = bufEnd = nextEnd = buf;
-  eof = gFalse;
-}
-
-//
-// When fillBuf finishes, buf[] looks like this:
-//   +-----+--------------+-----------------+--
-//   + tag | ... data ... | next 0, 1, or 2 |
-//   +-----+--------------+-----------------+--
-//    ^                    ^                 ^
-//    bufPtr               bufEnd            nextEnd
-//
-GBool RunLengthEncoder::fillBuf() {
-  int c, c1, c2;
-  int n;
-
-  // already hit EOF?
-  if (eof)
-    return gFalse;
-
-  // grab two bytes
-  if (nextEnd < bufEnd + 1) {
-    if ((c1 = str->getChar()) == EOF) {
-      eof = gTrue;
-      return gFalse;
-    }
-  } else {
-    c1 = bufEnd[0] & 0xff;
-  }
-  if (nextEnd < bufEnd + 2) {
-    if ((c2 = str->getChar()) == EOF) {
-      eof = gTrue;
-      buf[0] = 0;
-      buf[1] = c1;
-      bufPtr = buf;
-      bufEnd = &buf[2];
-      return gTrue;
-    }
-  } else {
-    c2 = bufEnd[1] & 0xff;
-  }
-
-  // check for repeat
-  c = 0; // make gcc happy
-  if (c1 == c2) {
-    n = 2;
-    while (n < 128 && (c = str->getChar()) == c1)
-      ++n;
-    buf[0] = (char)(257 - n);
-    buf[1] = c1;
-    bufEnd = &buf[2];
-    if (c == EOF) {
-      eof = gTrue;
-    } else if (n < 128) {
-      buf[2] = c;
-      nextEnd = &buf[3];
-    } else {
-      nextEnd = bufEnd;
-    }
-
-  // get up to 128 chars
-  } else {
-    buf[1] = c1;
-    buf[2] = c2;
-    n = 2;
-    while (n < 128) {
-      if ((c = str->getChar()) == EOF) {
-       eof = gTrue;
-       break;
-      }
-      ++n;
-      buf[n] = c;
-      if (buf[n] == buf[n-1])
-       break;
-    }
-    if (buf[n] == buf[n-1]) {
-      buf[0] = (char)(n-2-1);
-      bufEnd = &buf[n-1];
-      nextEnd = &buf[n+1];
-    } else {
-      buf[0] = (char)(n-1);
-      bufEnd = nextEnd = &buf[n+1];
-    }
-  }
-  bufPtr = buf;
-  return gTrue;
-}