source: trunk/poppler/mypoppler/poppler/Stream.cc @ 461

Last change on this file since 461 was 461, checked in by Silvan Scherrer, 11 years ago

poppler update to 0.14.2

File size: 101.2 KB
Line 
1//========================================================================
2//
3// Stream.cc
4//
5// Copyright 1996-2003 Glyph & Cog, LLC
6//
7//========================================================================
8
9//========================================================================
10//
11// Modified under the Poppler project - http://poppler.freedesktop.org
12//
13// All changes made under the Poppler project to this file are licensed
14// under GPL version 2 or later
15//
16// Copyright (C) 2005 Jeff Muizelaar <jeff@infidigm.net>
17// Copyright (C) 2006-2009 Albert Astals Cid <aacid@kde.org>
18// Copyright (C) 2007 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
19// Copyright (C) 2008 Julien Rebetez <julien@fhtagn.net>
20// Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
21// Copyright (C) 2009 Glenn Ganz <glenn.ganz@uptime.ch>
22// Copyright (C) 2009 Stefan Thomas <thomas@eload24.com>
23// Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
24//
25// To see a description of the changes please see the Changelog file that
26// came with your tarball or type make ChangeLog if you are building from git
27//
28//========================================================================
29
30#include <config.h>
31
32#ifdef USE_GCC_PRAGMAS
33#pragma implementation
34#endif
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <stddef.h>
39#include <limits.h>
40#ifdef HAVE_UNISTD_H
41#include <unistd.h>
42#endif
43#include <string.h>
44#include <ctype.h>
45#include "goo/gmem.h"
46#include "goo/gfile.h"
47#include "poppler-config.h"
48#include "Error.h"
49#include "Object.h"
50#include "Lexer.h"
51#include "GfxState.h"
52#include "Stream.h"
53#include "JBIG2Stream.h"
54#include "Stream-CCITT.h"
55#include "CachedFile.h"
56
57#ifdef ENABLE_LIBJPEG
58#include "DCTStream.h"
59#endif
60
61#ifdef ENABLE_ZLIB
62#include "FlateStream.h"
63#endif
64
65#ifdef ENABLE_LIBOPENJPEG
66#include "JPEG2000Stream.h"
67#else
68#include "JPXStream.h"
69#endif
70
71#ifdef __DJGPP__
72static GBool setDJSYSFLAGS = gFalse;
73#endif
74
75#ifdef VMS
76#ifdef __GNUC__
77#define SEEK_SET 0
78#define SEEK_CUR 1
79#define SEEK_END 2
80#endif
81#endif
82
83//------------------------------------------------------------------------
84// Stream (base class)
85//------------------------------------------------------------------------
86
87Stream::Stream() {
88  ref = 1;
89}
90
91Stream::~Stream() {
92}
93
94void Stream::close() {
95}
96
97int Stream::getRawChar() {
98  error(-1, "Internal: called getRawChar() on non-predictor stream");
99  return EOF;
100}
101
102char *Stream::getLine(char *buf, int size) {
103  int i;
104  int c;
105
106  if (lookChar() == EOF)
107    return NULL;
108  for (i = 0; i < size - 1; ++i) {
109    c = getChar();
110    if (c == EOF || c == '\n')
111      break;
112    if (c == '\r') {
113      if ((c = lookChar()) == '\n')
114        getChar();
115      break;
116    }
117    buf[i] = c;
118  }
119  buf[i] = '\0';
120  return buf;
121}
122
123GooString *Stream::getPSFilter(int psLevel, char *indent) {
124  return new GooString();
125}
126
127Stream *Stream::addFilters(Object *dict) {
128  Object obj, obj2;
129  Object params, params2;
130  Stream *str;
131  int i;
132
133  str = this;
134  dict->dictLookup("Filter", &obj);
135  if (obj.isNull()) {
136    obj.free();
137    dict->dictLookup("F", &obj);
138  }
139  dict->dictLookup("DecodeParms", &params);
140  if (params.isNull()) {
141    params.free();
142    dict->dictLookup("DP", &params);
143  }
144  if (obj.isName()) {
145    str = makeFilter(obj.getName(), str, &params);
146  } else if (obj.isArray()) {
147    for (i = 0; i < obj.arrayGetLength(); ++i) {
148      obj.arrayGet(i, &obj2);
149      if (params.isArray())
150        params.arrayGet(i, &params2);
151      else
152        params2.initNull();
153      if (obj2.isName()) {
154        str = makeFilter(obj2.getName(), str, &params2);
155      } else {
156        error(getPos(), "Bad filter name");
157        str = new EOFStream(str);
158      }
159      obj2.free();
160      params2.free();
161    }
162  } else if (!obj.isNull()) {
163    error(getPos(), "Bad 'Filter' attribute in stream");
164  }
165  obj.free();
166  params.free();
167
168  return str;
169}
170
171Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
172  int pred;                     // parameters
173  int colors;
174  int bits;
175  int early;
176  int encoding;
177  GBool endOfLine, byteAlign, endOfBlock, black;
178  int columns, rows;
179  int colorXform;
180  Object globals, obj;
181
182  if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
183    str = new ASCIIHexStream(str);
184  } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
185    str = new ASCII85Stream(str);
186  } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
187    pred = 1;
188    columns = 1;
189    colors = 1;
190    bits = 8;
191    early = 1;
192    if (params->isDict()) {
193      params->dictLookup("Predictor", &obj);
194      if (obj.isInt())
195        pred = obj.getInt();
196      obj.free();
197      params->dictLookup("Columns", &obj);
198      if (obj.isInt())
199        columns = obj.getInt();
200      obj.free();
201      params->dictLookup("Colors", &obj);
202      if (obj.isInt())
203        colors = obj.getInt();
204      obj.free();
205      params->dictLookup("BitsPerComponent", &obj);
206      if (obj.isInt())
207        bits = obj.getInt();
208      obj.free();
209      params->dictLookup("EarlyChange", &obj);
210      if (obj.isInt())
211        early = obj.getInt();
212      obj.free();
213    }
214    str = new LZWStream(str, pred, columns, colors, bits, early);
215  } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
216    str = new RunLengthStream(str);
217  } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
218    encoding = 0;
219    endOfLine = gFalse;
220    byteAlign = gFalse;
221    columns = 1728;
222    rows = 0;
223    endOfBlock = gTrue;
224    black = gFalse;
225    if (params->isDict()) {
226      params->dictLookup("K", &obj);
227      if (obj.isInt()) {
228        encoding = obj.getInt();
229      }
230      obj.free();
231      params->dictLookup("EndOfLine", &obj);
232      if (obj.isBool()) {
233        endOfLine = obj.getBool();
234      }
235      obj.free();
236      params->dictLookup("EncodedByteAlign", &obj);
237      if (obj.isBool()) {
238        byteAlign = obj.getBool();
239      }
240      obj.free();
241      params->dictLookup("Columns", &obj);
242      if (obj.isInt()) {
243        columns = obj.getInt();
244      }
245      obj.free();
246      params->dictLookup("Rows", &obj);
247      if (obj.isInt()) {
248        rows = obj.getInt();
249      }
250      obj.free();
251      params->dictLookup("EndOfBlock", &obj);
252      if (obj.isBool()) {
253        endOfBlock = obj.getBool();
254      }
255      obj.free();
256      params->dictLookup("BlackIs1", &obj);
257      if (obj.isBool()) {
258        black = obj.getBool();
259      }
260      obj.free();
261    }
262    str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
263                             columns, rows, endOfBlock, black);
264  } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
265    colorXform = -1;
266    if (params->isDict()) {
267      if (params->dictLookup("ColorTransform", &obj)->isInt()) {
268        colorXform = obj.getInt();
269      }
270      obj.free();
271    }
272    str = new DCTStream(str, colorXform);
273  } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
274    pred = 1;
275    columns = 1;
276    colors = 1;
277    bits = 8;
278    if (params->isDict()) {
279      params->dictLookup("Predictor", &obj);
280      if (obj.isInt())
281        pred = obj.getInt();
282      obj.free();
283      params->dictLookup("Columns", &obj);
284      if (obj.isInt())
285        columns = obj.getInt();
286      obj.free();
287      params->dictLookup("Colors", &obj);
288      if (obj.isInt())
289        colors = obj.getInt();
290      obj.free();
291      params->dictLookup("BitsPerComponent", &obj);
292      if (obj.isInt())
293        bits = obj.getInt();
294      obj.free();
295    }
296    str = new FlateStream(str, pred, columns, colors, bits);
297  } else if (!strcmp(name, "JBIG2Decode")) {
298    if (params->isDict()) {
299      params->dictLookup("JBIG2Globals", &globals);
300    }
301    str = new JBIG2Stream(str, &globals);
302    globals.free();
303  } else if (!strcmp(name, "JPXDecode")) {
304    str = new JPXStream(str);
305  } else {
306    error(getPos(), "Unknown filter '%s'", name);
307    str = new EOFStream(str);
308  }
309  return str;
310}
311
312//------------------------------------------------------------------------
313// OutStream
314//------------------------------------------------------------------------
315OutStream::OutStream ()
316{
317  ref = 1;
318}
319
320OutStream::~OutStream ()
321{
322}
323
324//------------------------------------------------------------------------
325// FileOutStream
326//------------------------------------------------------------------------
327FileOutStream::FileOutStream (FILE* fa, Guint startA)
328{
329  f = fa;
330  start = startA;
331}
332
333FileOutStream::~FileOutStream ()
334{
335  close ();
336}
337
338void FileOutStream::close ()
339{
340
341}
342
343int FileOutStream::getPos ()
344{
345  return ftell(f);
346}
347
348void FileOutStream::put (char c)
349{
350  fputc(c,f);
351}
352
353void FileOutStream::printf(const char *format, ...)
354{
355  va_list argptr;
356  va_start (argptr, format);
357  vfprintf(f, format, argptr);
358  va_end (argptr);
359}
360
361
362//------------------------------------------------------------------------
363// BaseStream
364//------------------------------------------------------------------------
365
366BaseStream::BaseStream(Object *dictA) {
367  dict = *dictA;
368}
369
370BaseStream::~BaseStream() {
371  dict.free();
372}
373
374//------------------------------------------------------------------------
375// FilterStream
376//------------------------------------------------------------------------
377
378FilterStream::FilterStream(Stream *strA) {
379  str = strA;
380}
381
382FilterStream::~FilterStream() {
383}
384
385void FilterStream::close() {
386  str->close();
387}
388
389void FilterStream::setPos(Guint pos, int dir) {
390  error(-1, "Internal: called setPos() on FilterStream");
391}
392
393//------------------------------------------------------------------------
394// ImageStream
395//------------------------------------------------------------------------
396
397ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
398  int imgLineSize;
399
400  str = strA;
401  width = widthA;
402  nComps = nCompsA;
403  nBits = nBitsA;
404
405  nVals = width * nComps;
406  if (nBits == 1) {
407    imgLineSize = (nVals + 7) & ~7;
408  } else {
409    imgLineSize = nVals;
410  }
411  if (width > INT_MAX / nComps) {
412    // force a call to gmallocn(-1,...), which will throw an exception
413    imgLineSize = -1;
414  }
415  imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar));
416  imgIdx = nVals;
417}
418
419ImageStream::~ImageStream() {
420  gfree(imgLine);
421}
422
423void ImageStream::reset() {
424  str->reset();
425}
426
427void ImageStream::close() {
428  str->close();
429}
430
431GBool ImageStream::getPixel(Guchar *pix) {
432  int i;
433
434  if (imgIdx >= nVals) {
435    getLine();
436    imgIdx = 0;
437  }
438  for (i = 0; i < nComps; ++i) {
439    pix[i] = imgLine[imgIdx++];
440  }
441  return gTrue;
442}
443
444Guchar *ImageStream::getLine() {
445  Gulong buf, bitMask;
446  int bits;
447  int c;
448  int i;
449
450  if (nBits == 1) {
451    for (i = 0; i < nVals; i += 8) {
452      c = str->getChar();
453      imgLine[i+0] = (Guchar)((c >> 7) & 1);
454      imgLine[i+1] = (Guchar)((c >> 6) & 1);
455      imgLine[i+2] = (Guchar)((c >> 5) & 1);
456      imgLine[i+3] = (Guchar)((c >> 4) & 1);
457      imgLine[i+4] = (Guchar)((c >> 3) & 1);
458      imgLine[i+5] = (Guchar)((c >> 2) & 1);
459      imgLine[i+6] = (Guchar)((c >> 1) & 1);
460      imgLine[i+7] = (Guchar)(c & 1);
461    }
462  } else if (nBits == 8) {
463    Guchar *line = imgLine;
464    for (i = 0; i < nVals; ++i) {
465      *line++ = str->getChar();
466    }
467  } else if (nBits == 16) {
468    // this is a hack to support 16 bits images, everywhere
469    // we assume a component fits in 8 bits, with this hack
470    // we treat 16 bit images as 8 bit ones until it's fixed correctly.
471    // The hack has another part on GfxImageColorMap::GfxImageColorMap
472    for (i = 0; i < nVals; ++i) {
473      imgLine[i] = str->getChar();
474      str->getChar();
475    }
476  } else {
477    bitMask = (1 << nBits) - 1;
478    buf = 0;
479    bits = 0;
480    for (i = 0; i < nVals; ++i) {
481      if (bits < nBits) {
482        buf = (buf << 8) | (str->getChar() & 0xff);
483        bits += 8;
484      }
485      imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
486      bits -= nBits;
487    }
488  }
489  return imgLine;
490}
491
492void ImageStream::skipLine() {
493  int n, i;
494
495  n = (nVals * nBits + 7) >> 3;
496  for (i = 0; i < n; ++i) {
497    str->getChar();
498  }
499}
500
501//------------------------------------------------------------------------
502// StreamPredictor
503//------------------------------------------------------------------------
504
505StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
506                                 int widthA, int nCompsA, int nBitsA) {
507  str = strA;
508  predictor = predictorA;
509  width = widthA;
510  nComps = nCompsA;
511  nBits = nBitsA;
512  predLine = NULL;
513  ok = gFalse;
514
515  nVals = width * nComps;
516  pixBytes = (nComps * nBits + 7) >> 3;
517  rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
518  if (width <= 0 || nComps <= 0 || nBits <= 0 ||
519      nComps > gfxColorMaxComps ||
520      nBits > 16 ||
521      width >= INT_MAX / nComps ||      // check for overflow in nVals
522      nVals >= (INT_MAX - 7) / nBits) { // check for overflow in rowBytes
523    return;
524  }
525  predLine = (Guchar *)gmalloc(rowBytes);
526  memset(predLine, 0, rowBytes);
527  predIdx = rowBytes;
528
529  ok = gTrue;
530}
531
532StreamPredictor::~StreamPredictor() {
533  gfree(predLine);
534}
535
536int StreamPredictor::lookChar() {
537  if (predIdx >= rowBytes) {
538    if (!getNextLine()) {
539      return EOF;
540    }
541  }
542  return predLine[predIdx];
543}
544
545int StreamPredictor::getChar() {
546  if (predIdx >= rowBytes) {
547    if (!getNextLine()) {
548      return EOF;
549    }
550  }
551  return predLine[predIdx++];
552}
553
554GBool StreamPredictor::getNextLine() {
555  int curPred;
556  Guchar upLeftBuf[gfxColorMaxComps * 2 + 1];
557  int left, up, upLeft, p, pa, pb, pc;
558  int c;
559  Gulong inBuf, outBuf, bitMask;
560  int inBits, outBits;
561  int i, j, k, kk;
562
563  // get PNG optimum predictor number
564  if (predictor >= 10) {
565    if ((curPred = str->getRawChar()) == EOF) {
566      return gFalse;
567    }
568    curPred += 10;
569  } else {
570    curPred = predictor;
571  }
572
573  // read the raw line, apply PNG (byte) predictor
574  memset(upLeftBuf, 0, pixBytes + 1);
575  for (i = pixBytes; i < rowBytes; ++i) {
576    for (j = pixBytes; j > 0; --j) {
577      upLeftBuf[j] = upLeftBuf[j-1];
578    }
579    upLeftBuf[0] = predLine[i];
580    if ((c = str->getRawChar()) == EOF) {
581      if (i > pixBytes) {
582        // this ought to return false, but some (broken) PDF files
583        // contain truncated image data, and Adobe apparently reads the
584        // last partial line
585        break;
586      }
587      return gFalse;
588    }
589    switch (curPred) {
590    case 11:                    // PNG sub
591      predLine[i] = predLine[i - pixBytes] + (Guchar)c;
592      break;
593    case 12:                    // PNG up
594      predLine[i] = predLine[i] + (Guchar)c;
595      break;
596    case 13:                    // PNG average
597      predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
598                    (Guchar)c;
599      break;
600    case 14:                    // PNG Paeth
601      left = predLine[i - pixBytes];
602      up = predLine[i];
603      upLeft = upLeftBuf[pixBytes];
604      p = left + up - upLeft;
605      if ((pa = p - left) < 0)
606        pa = -pa;
607      if ((pb = p - up) < 0)
608        pb = -pb;
609      if ((pc = p - upLeft) < 0)
610        pc = -pc;
611      if (pa <= pb && pa <= pc)
612        predLine[i] = left + (Guchar)c;
613      else if (pb <= pc)
614        predLine[i] = up + (Guchar)c;
615      else
616        predLine[i] = upLeft + (Guchar)c;
617      break;
618    case 10:                    // PNG none
619    default:                    // no predictor or TIFF predictor
620      predLine[i] = (Guchar)c;
621      break;
622    }
623  }
624
625  // apply TIFF (component) predictor
626  if (predictor == 2) {
627    if (nBits == 1) {
628      inBuf = predLine[pixBytes - 1];
629      for (i = pixBytes; i < rowBytes; i += 8) {
630        // 1-bit add is just xor
631        inBuf = (inBuf << 8) | predLine[i];
632        predLine[i] ^= inBuf >> nComps;
633      }
634    } else if (nBits == 8) {
635      for (i = pixBytes; i < rowBytes; ++i) {
636        predLine[i] += predLine[i - nComps];
637      }
638    } else {
639      memset(upLeftBuf, 0, nComps + 1);
640      bitMask = (1 << nBits) - 1;
641      inBuf = outBuf = 0;
642      inBits = outBits = 0;
643      j = k = pixBytes;
644      for (i = 0; i < width; ++i) {
645        for (kk = 0; kk < nComps; ++kk) {
646          if (inBits < nBits) {
647            inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
648            inBits += 8;
649          }
650          upLeftBuf[kk] = (Guchar)((upLeftBuf[kk] +
651                                    (inBuf >> (inBits - nBits))) & bitMask);
652          inBits -= nBits;
653          outBuf = (outBuf << nBits) | upLeftBuf[kk];
654          outBits += nBits;
655          if (outBits >= 8) {
656            predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
657            outBits -= 8;
658          }
659        }
660      }
661      if (outBits > 0) {
662        predLine[k++] = (Guchar)((outBuf << (8 - outBits)) +
663                                 (inBuf & ((1 << (8 - outBits)) - 1)));
664      }
665    }
666  }
667
668  // reset to start of line
669  predIdx = pixBytes;
670
671  return gTrue;
672}
673
674//------------------------------------------------------------------------
675// FileStream
676//------------------------------------------------------------------------
677
678FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
679                       Guint lengthA, Object *dictA):
680    BaseStream(dictA) {
681  f = fA;
682  start = startA;
683  limited = limitedA;
684  length = lengthA;
685  bufPtr = bufEnd = buf;
686  bufPos = start;
687  savePos = 0;
688  saved = gFalse;
689}
690
691FileStream::~FileStream() {
692  close();
693}
694
695Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
696                                  Guint lengthA, Object *dictA) {
697  return new FileStream(f, startA, limitedA, lengthA, dictA);
698}
699
700void FileStream::reset() {
701#if HAVE_FSEEKO
702  savePos = (Guint)ftello(f);
703  fseeko(f, start, SEEK_SET);
704#elif HAVE_FSEEK64
705  savePos = (Guint)ftell64(f);
706  fseek64(f, start, SEEK_SET);
707#else
708  savePos = (Guint)ftell(f);
709  fseek(f, start, SEEK_SET);
710#endif
711  saved = gTrue;
712  bufPtr = bufEnd = buf;
713  bufPos = start;
714}
715
716void FileStream::close() {
717  if (saved) {
718#if HAVE_FSEEKO
719    fseeko(f, savePos, SEEK_SET);
720#elif HAVE_FSEEK64
721    fseek64(f, savePos, SEEK_SET);
722#else
723    fseek(f, savePos, SEEK_SET);
724#endif
725    saved = gFalse;
726  }
727}
728
729GBool FileStream::fillBuf() {
730  int n;
731
732  bufPos += bufEnd - buf;
733  bufPtr = bufEnd = buf;
734  if (limited && bufPos >= start + length) {
735    return gFalse;
736  }
737  if (limited && bufPos + fileStreamBufSize > start + length) {
738    n = start + length - bufPos;
739  } else {
740    n = fileStreamBufSize;
741  }
742  n = fread(buf, 1, n, f);
743  bufEnd = buf + n;
744  if (bufPtr >= bufEnd) {
745    return gFalse;
746  }
747  return gTrue;
748}
749
750void FileStream::setPos(Guint pos, int dir) {
751  Guint size;
752
753  if (dir >= 0) {
754#if HAVE_FSEEKO
755    fseeko(f, pos, SEEK_SET);
756#elif HAVE_FSEEK64
757    fseek64(f, pos, SEEK_SET);
758#else
759    fseek(f, pos, SEEK_SET);
760#endif
761    bufPos = pos;
762  } else {
763#if HAVE_FSEEKO
764    fseeko(f, 0, SEEK_END);
765    size = (Guint)ftello(f);
766#elif HAVE_FSEEK64
767    fseek64(f, 0, SEEK_END);
768    size = (Guint)ftell64(f);
769#else
770    fseek(f, 0, SEEK_END);
771    size = (Guint)ftell(f);
772#endif
773    if (pos > size)
774      pos = (Guint)size;
775#ifdef __CYGWIN32__
776    //~ work around a bug in cygwin's implementation of fseek
777    rewind(f);
778#endif
779#if HAVE_FSEEKO
780    fseeko(f, -(int)pos, SEEK_END);
781    bufPos = (Guint)ftello(f);
782#elif HAVE_FSEEK64
783    fseek64(f, -(int)pos, SEEK_END);
784    bufPos = (Guint)ftell64(f);
785#else
786    fseek(f, -(int)pos, SEEK_END);
787    bufPos = (Guint)ftell(f);
788#endif
789  }
790  bufPtr = bufEnd = buf;
791}
792
793void FileStream::moveStart(int delta) {
794  start += delta;
795  bufPtr = bufEnd = buf;
796  bufPos = start;
797}
798
799//------------------------------------------------------------------------
800// CachedFileStream
801//------------------------------------------------------------------------
802
803CachedFileStream::CachedFileStream(CachedFile *ccA, Guint startA,
804        GBool limitedA, Guint lengthA, Object *dictA)
805  : BaseStream(dictA)
806{
807  cc = ccA;
808  start = startA;
809  limited = limitedA;
810  length = lengthA;
811  bufPtr = bufEnd = buf;
812  bufPos = start;
813  savePos = 0;
814  saved = gFalse;
815}
816
817CachedFileStream::~CachedFileStream()
818{
819  close();
820  cc->decRefCnt();
821}
822
823Stream *CachedFileStream::makeSubStream(Guint startA, GBool limitedA,
824        Guint lengthA, Object *dictA)
825{
826  cc->incRefCnt();
827  return new CachedFileStream(cc, startA, limitedA, lengthA, dictA);
828}
829
830void CachedFileStream::reset()
831{
832  savePos = (Guint)cc->tell();
833  cc->seek(start, SEEK_SET);
834
835  saved = gTrue;
836  bufPtr = bufEnd = buf;
837  bufPos = start;
838}
839
840void CachedFileStream::close()
841{
842  if (saved) {
843    cc->seek(savePos, SEEK_SET);
844    saved = gFalse;
845  }
846}
847
848GBool CachedFileStream::fillBuf()
849{
850  int n;
851
852  bufPos += bufEnd - buf;
853  bufPtr = bufEnd = buf;
854  if (limited && bufPos >= start + length) {
855    return gFalse;
856  }
857  if (limited && bufPos + cachedStreamBufSize > start + length) {
858    n = start + length - bufPos;
859  } else {
860    n = cachedStreamBufSize;
861  }
862  cc->read(buf, 1, n);
863  bufEnd = buf + n;
864  if (bufPtr >= bufEnd) {
865    return gFalse;
866  }
867  return gTrue;
868}
869
870void CachedFileStream::setPos(Guint pos, int dir)
871{
872  Guint size;
873
874  if (dir >= 0) {
875    cc->seek(pos, SEEK_SET);
876    bufPos = pos;
877  } else {
878    cc->seek(0, SEEK_END);
879    size = (Guint)cc->tell();
880
881    if (pos > size)
882      pos = (Guint)size;
883
884    cc->seek(-(int)pos, SEEK_END);
885    bufPos = (Guint)cc->tell();
886  }
887
888  bufPtr = bufEnd = buf;
889}
890
891void CachedFileStream::moveStart(int delta)
892{
893  start += delta;
894  bufPtr = bufEnd = buf;
895  bufPos = start;
896}
897
898//------------------------------------------------------------------------
899// MemStream
900//------------------------------------------------------------------------
901
902MemStream::MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA):
903    BaseStream(dictA) {
904  buf = bufA;
905  start = startA;
906  length = lengthA;
907  bufEnd = buf + start + length;
908  bufPtr = buf + start;
909  needFree = gFalse;
910}
911
912MemStream::~MemStream() {
913  if (needFree) {
914    gfree(buf);
915  }
916}
917
918Stream *MemStream::makeSubStream(Guint startA, GBool limited,
919                                 Guint lengthA, Object *dictA) {
920  MemStream *subStr;
921  Guint newLength;
922
923  if (!limited || startA + lengthA > start + length) {
924    newLength = start + length - startA;
925  } else {
926    newLength = lengthA;
927  }
928  subStr = new MemStream(buf, startA, newLength, dictA);
929  return subStr;
930}
931
932void MemStream::reset() {
933  bufPtr = buf + start;
934}
935
936void MemStream::close() {
937}
938
939void MemStream::setPos(Guint pos, int dir) {
940  Guint i;
941
942  if (dir >= 0) {
943    i = pos;
944  } else {
945    i = start + length - pos;
946  }
947  if (i < start) {
948    i = start;
949  } else if (i > start + length) {
950    i = start + length;
951  }
952  bufPtr = buf + i;
953}
954
955void MemStream::moveStart(int delta) {
956  start += delta;
957  length -= delta;
958  bufPtr = buf + start;
959}
960
961//------------------------------------------------------------------------
962// EmbedStream
963//------------------------------------------------------------------------
964
965EmbedStream::EmbedStream(Stream *strA, Object *dictA,
966                         GBool limitedA, Guint lengthA):
967    BaseStream(dictA) {
968  str = strA;
969  limited = limitedA;
970  length = lengthA;
971}
972
973EmbedStream::~EmbedStream() {
974}
975
976Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA,
977                                   Guint lengthA, Object *dictA) {
978  error(-1, "Internal: called makeSubStream() on EmbedStream");
979  return NULL;
980}
981
982int EmbedStream::getChar() {
983  if (limited && !length) {
984    return EOF;
985  }
986  --length;
987  return str->getChar();
988}
989
990int EmbedStream::lookChar() {
991  if (limited && !length) {
992    return EOF;
993  }
994  return str->lookChar();
995}
996
997void EmbedStream::setPos(Guint pos, int dir) {
998  error(-1, "Internal: called setPos() on EmbedStream");
999}
1000
1001Guint EmbedStream::getStart() {
1002  error(-1, "Internal: called getStart() on EmbedStream");
1003  return 0;
1004}
1005
1006void EmbedStream::moveStart(int delta) {
1007  error(-1, "Internal: called moveStart() on EmbedStream");
1008}
1009
1010//------------------------------------------------------------------------
1011// ASCIIHexStream
1012//------------------------------------------------------------------------
1013
1014ASCIIHexStream::ASCIIHexStream(Stream *strA):
1015    FilterStream(strA) {
1016  buf = EOF;
1017  eof = gFalse;
1018}
1019
1020ASCIIHexStream::~ASCIIHexStream() {
1021  delete str;
1022}
1023
1024void ASCIIHexStream::reset() {
1025  str->reset();
1026  buf = EOF;
1027  eof = gFalse;
1028}
1029
1030int ASCIIHexStream::lookChar() {
1031  int c1, c2, x;
1032
1033  if (buf != EOF)
1034    return buf;
1035  if (eof) {
1036    buf = EOF;
1037    return EOF;
1038  }
1039  do {
1040    c1 = str->getChar();
1041  } while (isspace(c1));
1042  if (c1 == '>') {
1043    eof = gTrue;
1044    buf = EOF;
1045    return buf;
1046  }
1047  do {
1048    c2 = str->getChar();
1049  } while (isspace(c2));
1050  if (c2 == '>') {
1051    eof = gTrue;
1052    c2 = '0';
1053  }
1054  if (c1 >= '0' && c1 <= '9') {
1055    x = (c1 - '0') << 4;
1056  } else if (c1 >= 'A' && c1 <= 'F') {
1057    x = (c1 - 'A' + 10) << 4;
1058  } else if (c1 >= 'a' && c1 <= 'f') {
1059    x = (c1 - 'a' + 10) << 4;
1060  } else if (c1 == EOF) {
1061    eof = gTrue;
1062    x = 0;
1063  } else {
1064    error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
1065    x = 0;
1066  }
1067  if (c2 >= '0' && c2 <= '9') {
1068    x += c2 - '0';
1069  } else if (c2 >= 'A' && c2 <= 'F') {
1070    x += c2 - 'A' + 10;
1071  } else if (c2 >= 'a' && c2 <= 'f') {
1072    x += c2 - 'a' + 10;
1073  } else if (c2 == EOF) {
1074    eof = gTrue;
1075    x = 0;
1076  } else {
1077    error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
1078  }
1079  buf = x & 0xff;
1080  return buf;
1081}
1082
1083GooString *ASCIIHexStream::getPSFilter(int psLevel, char *indent) {
1084  GooString *s;
1085
1086  if (psLevel < 2) {
1087    return NULL;
1088  }
1089  if (!(s = str->getPSFilter(psLevel, indent))) {
1090    return NULL;
1091  }
1092  s->append(indent)->append("/ASCIIHexDecode filter\n");
1093  return s;
1094}
1095
1096GBool ASCIIHexStream::isBinary(GBool last) {
1097  return str->isBinary(gFalse);
1098}
1099
1100//------------------------------------------------------------------------
1101// ASCII85Stream
1102//------------------------------------------------------------------------
1103
1104ASCII85Stream::ASCII85Stream(Stream *strA):
1105    FilterStream(strA) {
1106  index = n = 0;
1107  eof = gFalse;
1108}
1109
1110ASCII85Stream::~ASCII85Stream() {
1111  delete str;
1112}
1113
1114void ASCII85Stream::reset() {
1115  str->reset();
1116  index = n = 0;
1117  eof = gFalse;
1118}
1119
1120int ASCII85Stream::lookChar() {
1121  int k;
1122  Gulong t;
1123
1124  if (index >= n) {
1125    if (eof)
1126      return EOF;
1127    index = 0;
1128    do {
1129      c[0] = str->getChar();
1130    } while (Lexer::isSpace(c[0]));
1131    if (c[0] == '~' || c[0] == EOF) {
1132      eof = gTrue;
1133      n = 0;
1134      return EOF;
1135    } else if (c[0] == 'z') {
1136      b[0] = b[1] = b[2] = b[3] = 0;
1137      n = 4;
1138    } else {
1139      for (k = 1; k < 5; ++k) {
1140        do {
1141          c[k] = str->getChar();
1142        } while (Lexer::isSpace(c[k]));
1143        if (c[k] == '~' || c[k] == EOF)
1144          break;
1145      }
1146      n = k - 1;
1147      if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
1148        for (++k; k < 5; ++k)
1149          c[k] = 0x21 + 84;
1150        eof = gTrue;
1151      }
1152      t = 0;
1153      for (k = 0; k < 5; ++k)
1154        t = t * 85 + (c[k] - 0x21);
1155      for (k = 3; k >= 0; --k) {
1156        b[k] = (int)(t & 0xff);
1157        t >>= 8;
1158      }
1159    }
1160  }
1161  return b[index];
1162}
1163
1164GooString *ASCII85Stream::getPSFilter(int psLevel, char *indent) {
1165  GooString *s;
1166
1167  if (psLevel < 2) {
1168    return NULL;
1169  }
1170  if (!(s = str->getPSFilter(psLevel, indent))) {
1171    return NULL;
1172  }
1173  s->append(indent)->append("/ASCII85Decode filter\n");
1174  return s;
1175}
1176
1177GBool ASCII85Stream::isBinary(GBool last) {
1178  return str->isBinary(gFalse);
1179}
1180
1181//------------------------------------------------------------------------
1182// LZWStream
1183//------------------------------------------------------------------------
1184
1185LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
1186                     int bits, int earlyA):
1187    FilterStream(strA) {
1188  if (predictor != 1) {
1189    pred = new StreamPredictor(this, predictor, columns, colors, bits);
1190    if (!pred->isOk()) {
1191      delete pred;
1192      pred = NULL;
1193    }
1194  } else {
1195    pred = NULL;
1196  }
1197  early = earlyA;
1198  eof = gFalse;
1199  inputBits = 0;
1200  clearTable();
1201}
1202
1203LZWStream::~LZWStream() {
1204  if (pred) {
1205    delete pred;
1206  }
1207  delete str;
1208}
1209
1210int LZWStream::getChar() {
1211  if (pred) {
1212    return pred->getChar();
1213  }
1214  if (eof) {
1215    return EOF;
1216  }
1217  if (seqIndex >= seqLength) {
1218    if (!processNextCode()) {
1219      return EOF;
1220    }
1221  }
1222  return seqBuf[seqIndex++];
1223}
1224
1225int LZWStream::lookChar() {
1226  if (pred) {
1227    return pred->lookChar();
1228  }
1229  if (eof) {
1230    return EOF;
1231  }
1232  if (seqIndex >= seqLength) {
1233    if (!processNextCode()) {
1234      return EOF;
1235    }
1236  }
1237  return seqBuf[seqIndex];
1238}
1239
1240int LZWStream::getRawChar() {
1241  if (eof) {
1242    return EOF;
1243  }
1244  if (seqIndex >= seqLength) {
1245    if (!processNextCode()) {
1246      return EOF;
1247    }
1248  }
1249  return seqBuf[seqIndex++];
1250}
1251
1252void LZWStream::reset() {
1253  str->reset();
1254  eof = gFalse;
1255  inputBits = 0;
1256  clearTable();
1257}
1258
1259GBool LZWStream::processNextCode() {
1260  int code;
1261  int nextLength;
1262  int i, j;
1263
1264  // check for EOF
1265  if (eof) {
1266    return gFalse;
1267  }
1268
1269  // check for eod and clear-table codes
1270 start:
1271  code = getCode();
1272  if (code == EOF || code == 257) {
1273    eof = gTrue;
1274    return gFalse;
1275  }
1276  if (code == 256) {
1277    clearTable();
1278    goto start;
1279  }
1280  if (nextCode >= 4097) {
1281    error(getPos(), "Bad LZW stream - expected clear-table code");
1282    clearTable();
1283  }
1284
1285  // process the next code
1286  nextLength = seqLength + 1;
1287  if (code < 256) {
1288    seqBuf[0] = code;
1289    seqLength = 1;
1290  } else if (code < nextCode) {
1291    seqLength = table[code].length;
1292    for (i = seqLength - 1, j = code; i > 0; --i) {
1293      seqBuf[i] = table[j].tail;
1294      j = table[j].head;
1295    }
1296    seqBuf[0] = j;
1297  } else if (code == nextCode) {
1298    seqBuf[seqLength] = newChar;
1299    ++seqLength;
1300  } else {
1301    error(getPos(), "Bad LZW stream - unexpected code");
1302    eof = gTrue;
1303    return gFalse;
1304  }
1305  newChar = seqBuf[0];
1306  if (first) {
1307    first = gFalse;
1308  } else {
1309    table[nextCode].length = nextLength;
1310    table[nextCode].head = prevCode;
1311    table[nextCode].tail = newChar;
1312    ++nextCode;
1313    if (nextCode + early == 512)
1314      nextBits = 10;
1315    else if (nextCode + early == 1024)
1316      nextBits = 11;
1317    else if (nextCode + early == 2048)
1318      nextBits = 12;
1319  }
1320  prevCode = code;
1321
1322  // reset buffer
1323  seqIndex = 0;
1324
1325  return gTrue;
1326}
1327
1328void LZWStream::clearTable() {
1329  nextCode = 258;
1330  nextBits = 9;
1331  seqIndex = seqLength = 0;
1332  first = gTrue;
1333}
1334
1335int LZWStream::getCode() {
1336  int c;
1337  int code;
1338
1339  while (inputBits < nextBits) {
1340    if ((c = str->getChar()) == EOF)
1341      return EOF;
1342    inputBuf = (inputBuf << 8) | (c & 0xff);
1343    inputBits += 8;
1344  }
1345  code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
1346  inputBits -= nextBits;
1347  return code;
1348}
1349
1350GooString *LZWStream::getPSFilter(int psLevel, char *indent) {
1351  GooString *s;
1352
1353  if (psLevel < 2 || pred) {
1354    return NULL;
1355  }
1356  if (!(s = str->getPSFilter(psLevel, indent))) {
1357    return NULL;
1358  }
1359  s->append(indent)->append("<< ");
1360  if (!early) {
1361    s->append("/EarlyChange 0 ");
1362  }
1363  s->append(">> /LZWDecode filter\n");
1364  return s;
1365}
1366
1367GBool LZWStream::isBinary(GBool last) {
1368  return str->isBinary(gTrue);
1369}
1370
1371//------------------------------------------------------------------------
1372// RunLengthStream
1373//------------------------------------------------------------------------
1374
1375RunLengthStream::RunLengthStream(Stream *strA):
1376    FilterStream(strA) {
1377  bufPtr = bufEnd = buf;
1378  eof = gFalse;
1379}
1380
1381RunLengthStream::~RunLengthStream() {
1382  delete str;
1383}
1384
1385void RunLengthStream::reset() {
1386  str->reset();
1387  bufPtr = bufEnd = buf;
1388  eof = gFalse;
1389}
1390
1391GooString *RunLengthStream::getPSFilter(int psLevel, char *indent) {
1392  GooString *s;
1393
1394  if (psLevel < 2) {
1395    return NULL;
1396  }
1397  if (!(s = str->getPSFilter(psLevel, indent))) {
1398    return NULL;
1399  }
1400  s->append(indent)->append("/RunLengthDecode filter\n");
1401  return s;
1402}
1403
1404GBool RunLengthStream::isBinary(GBool last) {
1405  return str->isBinary(gTrue);
1406}
1407
1408GBool RunLengthStream::fillBuf() {
1409  int c;
1410  int n, i;
1411
1412  if (eof)
1413    return gFalse;
1414  c = str->getChar();
1415  if (c == 0x80 || c == EOF) {
1416    eof = gTrue;
1417    return gFalse;
1418  }
1419  if (c < 0x80) {
1420    n = c + 1;
1421    for (i = 0; i < n; ++i)
1422      buf[i] = (char)str->getChar();
1423  } else {
1424    n = 0x101 - c;
1425    c = str->getChar();
1426    for (i = 0; i < n; ++i)
1427      buf[i] = (char)c;
1428  }
1429  bufPtr = buf;
1430  bufEnd = buf + n;
1431  return gTrue;
1432}
1433
1434//------------------------------------------------------------------------
1435// CCITTFaxStream
1436//------------------------------------------------------------------------
1437
1438CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
1439                               GBool byteAlignA, int columnsA, int rowsA,
1440                               GBool endOfBlockA, GBool blackA):
1441    FilterStream(strA) {
1442  encoding = encodingA;
1443  endOfLine = endOfLineA;
1444  byteAlign = byteAlignA;
1445  columns = columnsA;
1446  if (columns < 1) {
1447    columns = 1;
1448  } else if (columns > INT_MAX - 2) {
1449    columns = INT_MAX - 2;
1450  }
1451  rows = rowsA;
1452  endOfBlock = endOfBlockA;
1453  black = blackA;
1454  // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = columns
1455  // ---> max codingLine size = columns + 1
1456  // refLine has one extra guard entry at the end
1457  // ---> max refLine size = columns + 2
1458  codingLine = (int *)gmallocn_checkoverflow(columns + 1, sizeof(int));
1459  refLine = (int *)gmallocn_checkoverflow(columns + 2, sizeof(int));
1460
1461  if (codingLine != NULL && refLine != NULL) {
1462    eof = gFalse;
1463    codingLine[0] = columns;
1464  } else {
1465    eof = gTrue;
1466  }
1467  row = 0;
1468  nextLine2D = encoding < 0;
1469  inputBits = 0;
1470  a0i = 0;
1471  outputBits = 0;
1472
1473  buf = EOF;
1474}
1475
1476CCITTFaxStream::~CCITTFaxStream() {
1477  delete str;
1478  gfree(refLine);
1479  gfree(codingLine);
1480}
1481
1482void CCITTFaxStream::unfilteredReset () {
1483  str->reset();
1484
1485  row = 0;
1486  nextLine2D = encoding < 0;
1487  inputBits = 0;
1488  a0i = 0;
1489  outputBits = 0;
1490  buf = EOF;
1491}
1492
1493void CCITTFaxStream::reset() {
1494  short code1;
1495
1496  unfilteredReset();
1497
1498  if (codingLine != NULL && refLine != NULL) {
1499    eof = gFalse;
1500    codingLine[0] = columns;
1501  } else {
1502    eof = gTrue;
1503  }
1504
1505  // skip any initial zero bits and end-of-line marker, and get the 2D
1506  // encoding tag
1507  while ((code1 = lookBits(12)) == 0) {
1508    eatBits(1);
1509  }
1510  if (code1 == 0x001) {
1511    eatBits(12);
1512  }
1513  if (encoding > 0) {
1514    nextLine2D = !lookBits(1);
1515    eatBits(1);
1516  }
1517}
1518
1519inline void CCITTFaxStream::addPixels(int a1, int blackPixels) {
1520  if (a1 > codingLine[a0i]) {
1521    if (a1 > columns) {
1522      error(getPos(), "CCITTFax row is wrong length (%d)", a1);
1523      err = gTrue;
1524      a1 = columns;
1525    }
1526    if ((a0i & 1) ^ blackPixels) {
1527      ++a0i;
1528    }
1529    codingLine[a0i] = a1;
1530  }
1531}
1532
1533inline void CCITTFaxStream::addPixelsNeg(int a1, int blackPixels) {
1534  if (a1 > codingLine[a0i]) {
1535    if (a1 > columns) {
1536      error(getPos(), "CCITTFax row is wrong length (%d)", a1);
1537      err = gTrue;
1538      a1 = columns;
1539    }
1540    if ((a0i & 1) ^ blackPixels) {
1541      ++a0i;
1542    }
1543    codingLine[a0i] = a1;
1544  } else if (a1 < codingLine[a0i]) {
1545    if (a1 < 0) {
1546      error(getPos(), "Invalid CCITTFax code");
1547      err = gTrue;
1548      a1 = 0;
1549    }
1550    while (a0i > 0 && a1 <= codingLine[a0i - 1]) {
1551      --a0i;
1552    }
1553    codingLine[a0i] = a1;
1554  }
1555}
1556
1557int CCITTFaxStream::lookChar() {
1558  short code1, code2, code3;
1559  int b1i, blackPixels, i, bits;
1560  GBool gotEOL;
1561
1562  if (buf != EOF) {
1563    return buf;
1564  }
1565
1566  // read the next row
1567  if (outputBits == 0) {
1568
1569    // if at eof just return EOF
1570    if (eof) {
1571      return EOF;
1572    }
1573
1574    err = gFalse;
1575
1576    // 2-D encoding
1577    if (nextLine2D) {
1578      for (i = 0; codingLine[i] < columns; ++i) {
1579        refLine[i] = codingLine[i];
1580      }
1581      refLine[i++] = columns;
1582      refLine[i] = columns;
1583      codingLine[0] = 0;
1584      a0i = 0;
1585      b1i = 0;
1586      blackPixels = 0;
1587      // invariant:
1588      // refLine[b1i-1] <= codingLine[a0i] < refLine[b1i] < refLine[b1i+1]
1589      //                                                             <= columns
1590      // exception at left edge:
1591      //   codingLine[a0i = 0] = refLine[b1i = 0] = 0 is possible
1592      // exception at right edge:
1593      //   refLine[b1i] = refLine[b1i+1] = columns is possible
1594      while (codingLine[a0i] < columns) {
1595        code1 = getTwoDimCode();
1596        switch (code1) {
1597        case twoDimPass:
1598          addPixels(refLine[b1i + 1], blackPixels);
1599          if (refLine[b1i + 1] < columns) {
1600            b1i += 2;
1601          }
1602          break;
1603        case twoDimHoriz:
1604          code1 = code2 = 0;
1605          if (blackPixels) {
1606            do {
1607              code1 += code3 = getBlackCode();
1608            } while (code3 >= 64);
1609            do {
1610              code2 += code3 = getWhiteCode();
1611            } while (code3 >= 64);
1612          } else {
1613            do {
1614              code1 += code3 = getWhiteCode();
1615            } while (code3 >= 64);
1616            do {
1617              code2 += code3 = getBlackCode();
1618            } while (code3 >= 64);
1619          }
1620          addPixels(codingLine[a0i] + code1, blackPixels);
1621          if (codingLine[a0i] < columns) {
1622            addPixels(codingLine[a0i] + code2, blackPixels ^ 1);
1623          }
1624          while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1625            b1i += 2;
1626          }
1627          break;
1628        case twoDimVertR3:
1629          addPixels(refLine[b1i] + 3, blackPixels);
1630          blackPixels ^= 1;
1631          if (codingLine[a0i] < columns) {
1632            ++b1i;
1633            while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1634              b1i += 2;
1635            }
1636          }
1637          break;
1638        case twoDimVertR2:
1639          addPixels(refLine[b1i] + 2, blackPixels);
1640          blackPixels ^= 1;
1641          if (codingLine[a0i] < columns) {
1642            ++b1i;
1643            while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1644              b1i += 2;
1645            }
1646          }
1647          break;
1648        case twoDimVertR1:
1649          addPixels(refLine[b1i] + 1, blackPixels);
1650          blackPixels ^= 1;
1651          if (codingLine[a0i] < columns) {
1652            ++b1i;
1653            while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1654              b1i += 2;
1655            }
1656          }
1657          break;
1658        case twoDimVert0:
1659          addPixels(refLine[b1i], blackPixels);
1660          blackPixels ^= 1;
1661          if (codingLine[a0i] < columns) {
1662            ++b1i;
1663            while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1664              b1i += 2;
1665            }
1666          }
1667          break;
1668        case twoDimVertL3:
1669          addPixelsNeg(refLine[b1i] - 3, blackPixels);
1670          blackPixels ^= 1;
1671          if (codingLine[a0i] < columns) {
1672            if (b1i > 0) {
1673              --b1i;
1674            } else {
1675              ++b1i;
1676            }
1677            while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1678              b1i += 2;
1679            }
1680          }
1681          break;
1682        case twoDimVertL2:
1683          addPixelsNeg(refLine[b1i] - 2, blackPixels);
1684          blackPixels ^= 1;
1685          if (codingLine[a0i] < columns) {
1686            if (b1i > 0) {
1687              --b1i;
1688            } else {
1689              ++b1i;
1690            }
1691            while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1692              b1i += 2;
1693            }
1694          }
1695          break;
1696        case twoDimVertL1:
1697          addPixelsNeg(refLine[b1i] - 1, blackPixels);
1698          blackPixels ^= 1;
1699          if (codingLine[a0i] < columns) {
1700            if (b1i > 0) {
1701              --b1i;
1702            } else {
1703              ++b1i;
1704            }
1705            while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1706              b1i += 2;
1707            }
1708          }
1709          break;
1710        case EOF:
1711          addPixels(columns, 0);
1712          eof = gTrue;
1713          break;
1714        default:
1715          error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
1716          addPixels(columns, 0);
1717          err = gTrue;
1718          break;
1719        }
1720      }
1721
1722    // 1-D encoding
1723    } else {
1724      codingLine[0] = 0;
1725      a0i = 0;
1726      blackPixels = 0;
1727      while (codingLine[a0i] < columns) {
1728        code1 = 0;
1729        if (blackPixels) {
1730          do {
1731            code1 += code3 = getBlackCode();
1732          } while (code3 >= 64);
1733        } else {
1734          do {
1735            code1 += code3 = getWhiteCode();
1736          } while (code3 >= 64);
1737        }
1738        addPixels(codingLine[a0i] + code1, blackPixels);
1739        blackPixels ^= 1;
1740      }
1741    }
1742
1743    // byte-align the row
1744    if (byteAlign) {
1745      inputBits &= ~7;
1746    }
1747
1748    // check for end-of-line marker, skipping over any extra zero bits
1749    gotEOL = gFalse;
1750    if (!endOfBlock && row == rows - 1) {
1751      eof = gTrue;
1752    } else {
1753      code1 = lookBits(12);
1754      while (code1 == 0) {
1755        eatBits(1);
1756        code1 = lookBits(12);
1757      }
1758      if (code1 == 0x001) {
1759        eatBits(12);
1760        gotEOL = gTrue;
1761      } else if (code1 == EOF) {
1762        eof = gTrue;
1763      }
1764    }
1765
1766    // get 2D encoding tag
1767    if (!eof && encoding > 0) {
1768      nextLine2D = !lookBits(1);
1769      eatBits(1);
1770    }
1771
1772    // check for end-of-block marker
1773    if (endOfBlock && gotEOL) {
1774      code1 = lookBits(12);
1775      if (code1 == 0x001) {
1776        eatBits(12);
1777        if (encoding > 0) {
1778          lookBits(1);
1779          eatBits(1);
1780        }
1781        if (encoding >= 0) {
1782          for (i = 0; i < 4; ++i) {
1783            code1 = lookBits(12);
1784            if (code1 != 0x001) {
1785              error(getPos(), "Bad RTC code in CCITTFax stream");
1786            }
1787            eatBits(12);
1788            if (encoding > 0) {
1789              lookBits(1);
1790              eatBits(1);
1791            }
1792          }
1793        }
1794        eof = gTrue;
1795      }
1796
1797    // look for an end-of-line marker after an error -- we only do
1798    // this if we know the stream contains end-of-line markers because
1799    // the "just plow on" technique tends to work better otherwise
1800    } else if (err && endOfLine) {
1801      while (1) {
1802        code1 = lookBits(13);
1803        if (code1 == EOF) {
1804          eof = gTrue;
1805          return EOF;
1806        }
1807        if ((code1 >> 1) == 0x001) {
1808          break;
1809        }
1810        eatBits(1);
1811      }
1812      eatBits(12); 
1813      if (encoding > 0) {
1814        eatBits(1);
1815        nextLine2D = !(code1 & 1);
1816      }
1817    }
1818
1819    // set up for output
1820    if (codingLine[0] > 0) {
1821      outputBits = codingLine[a0i = 0];
1822    } else {
1823      outputBits = codingLine[a0i = 1];
1824    }
1825
1826    ++row;
1827  }
1828
1829  // get a byte
1830  if (outputBits >= 8) {
1831    buf = (a0i & 1) ? 0x00 : 0xff;
1832    outputBits -= 8;
1833    if (outputBits == 0 && codingLine[a0i] < columns) {
1834      ++a0i;
1835      outputBits = codingLine[a0i] - codingLine[a0i - 1];
1836    }
1837  } else {
1838    bits = 8;
1839    buf = 0;
1840    do {
1841      if (outputBits > bits) {
1842        buf <<= bits;
1843        if (!(a0i & 1)) {
1844          buf |= 0xff >> (8 - bits);
1845        }
1846        outputBits -= bits;
1847        bits = 0;
1848      } else {
1849        buf <<= outputBits;
1850        if (!(a0i & 1)) {
1851          buf |= 0xff >> (8 - outputBits);
1852        }
1853        bits -= outputBits;
1854        outputBits = 0;
1855        if (codingLine[a0i] < columns) {
1856          ++a0i;
1857          outputBits = codingLine[a0i] - codingLine[a0i - 1];
1858        } else if (bits > 0) {
1859          buf <<= bits;
1860          bits = 0;
1861        }
1862      }
1863    } while (bits);
1864  }
1865  if (black) {
1866    buf ^= 0xff;
1867  }
1868  return buf;
1869}
1870
1871short CCITTFaxStream::getTwoDimCode() {
1872  short code;
1873  const CCITTCode *p;
1874  int n;
1875
1876  code = 0; // make gcc happy
1877  if (endOfBlock) {
1878    code = lookBits(7);
1879    p = &twoDimTab1[code];
1880    if (p->bits > 0) {
1881      eatBits(p->bits);
1882      return p->n;
1883    }
1884  } else {
1885    for (n = 1; n <= 7; ++n) {
1886      code = lookBits(n);
1887      if (n < 7) {
1888        code <<= 7 - n;
1889      }
1890      p = &twoDimTab1[code];
1891      if (p->bits == n) {
1892        eatBits(n);
1893        return p->n;
1894      }
1895    }
1896  }
1897  error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
1898  return EOF;
1899}
1900
1901short CCITTFaxStream::getWhiteCode() {
1902  short code;
1903  const CCITTCode *p;
1904  int n;
1905
1906  code = 0; // make gcc happy
1907  if (endOfBlock) {
1908    code = lookBits(12);
1909    if (code == EOF) {
1910      return 1;
1911    }
1912    if ((code >> 5) == 0) {
1913      p = &whiteTab1[code];
1914    } else {
1915      p = &whiteTab2[code >> 3];
1916    }
1917    if (p->bits > 0) {
1918      eatBits(p->bits);
1919      return p->n;
1920    }
1921  } else {
1922    for (n = 1; n <= 9; ++n) {
1923      code = lookBits(n);
1924      if (code == EOF) {
1925        return 1;
1926      }
1927      if (n < 9) {
1928        code <<= 9 - n;
1929      }
1930      p = &whiteTab2[code];
1931      if (p->bits == n) {
1932        eatBits(n);
1933        return p->n;
1934      }
1935    }
1936    for (n = 11; n <= 12; ++n) {
1937      code = lookBits(n);
1938      if (code == EOF) {
1939        return 1;
1940      }
1941      if (n < 12) {
1942        code <<= 12 - n;
1943      }
1944      p = &whiteTab1[code];
1945      if (p->bits == n) {
1946        eatBits(n);
1947        return p->n;
1948      }
1949    }
1950  }
1951  error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
1952  // eat a bit and return a positive number so that the caller doesn't
1953  // go into an infinite loop
1954  eatBits(1);
1955  return 1;
1956}
1957
1958short CCITTFaxStream::getBlackCode() {
1959  short code;
1960  const CCITTCode *p;
1961  int n;
1962
1963  code = 0; // make gcc happy
1964  if (endOfBlock) {
1965    code = lookBits(13);
1966    if (code == EOF) {
1967      return 1;
1968    }
1969    if ((code >> 7) == 0) {
1970      p = &blackTab1[code];
1971    } else if ((code >> 9) == 0 && (code >> 7) != 0) {
1972      p = &blackTab2[(code >> 1) - 64];
1973    } else {
1974      p = &blackTab3[code >> 7];
1975    }
1976    if (p->bits > 0) {
1977      eatBits(p->bits);
1978      return p->n;
1979    }
1980  } else {
1981    for (n = 2; n <= 6; ++n) {
1982      code = lookBits(n);
1983      if (code == EOF) {
1984        return 1;
1985      }
1986      if (n < 6) {
1987        code <<= 6 - n;
1988      }
1989      p = &blackTab3[code];
1990      if (p->bits == n) {
1991        eatBits(n);
1992        return p->n;
1993      }
1994    }
1995    for (n = 7; n <= 12; ++n) {
1996      code = lookBits(n);
1997      if (code == EOF) {
1998        return 1;
1999      }
2000      if (n < 12) {
2001        code <<= 12 - n;
2002      }
2003      if (code >= 64) {
2004        p = &blackTab2[code - 64];
2005        if (p->bits == n) {
2006          eatBits(n);
2007          return p->n;
2008        }
2009      }
2010    }
2011    for (n = 10; n <= 13; ++n) {
2012      code = lookBits(n);
2013      if (code == EOF) {
2014        return 1;
2015      }
2016      if (n < 13) {
2017        code <<= 13 - n;
2018      }
2019      p = &blackTab1[code];
2020      if (p->bits == n) {
2021        eatBits(n);
2022        return p->n;
2023      }
2024    }
2025  }
2026  error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
2027  // eat a bit and return a positive number so that the caller doesn't
2028  // go into an infinite loop
2029  eatBits(1);
2030  return 1;
2031}
2032
2033short CCITTFaxStream::lookBits(int n) {
2034  int c;
2035
2036  while (inputBits < n) {
2037    if ((c = str->getChar()) == EOF) {
2038      if (inputBits == 0) {
2039        return EOF;
2040      }
2041      // near the end of the stream, the caller may ask for more bits
2042      // than are available, but there may still be a valid code in
2043      // however many bits are available -- we need to return correct
2044      // data in this case
2045      return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
2046    }
2047    inputBuf = (inputBuf << 8) + c;
2048    inputBits += 8;
2049  }
2050  return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
2051}
2052
2053GooString *CCITTFaxStream::getPSFilter(int psLevel, char *indent) {
2054  GooString *s;
2055  char s1[50];
2056
2057  if (psLevel < 2) {
2058    return NULL;
2059  }
2060  if (!(s = str->getPSFilter(psLevel, indent))) {
2061    return NULL;
2062  }
2063  s->append(indent)->append("<< ");
2064  if (encoding != 0) {
2065    sprintf(s1, "/K %d ", encoding);
2066    s->append(s1);
2067  }
2068  if (endOfLine) {
2069    s->append("/EndOfLine true ");
2070  }
2071  if (byteAlign) {
2072    s->append("/EncodedByteAlign true ");
2073  }
2074  sprintf(s1, "/Columns %d ", columns);
2075  s->append(s1);
2076  if (rows != 0) {
2077    sprintf(s1, "/Rows %d ", rows);
2078    s->append(s1);
2079  }
2080  if (!endOfBlock) {
2081    s->append("/EndOfBlock false ");
2082  }
2083  if (black) {
2084    s->append("/BlackIs1 true ");
2085  }
2086  s->append(">> /CCITTFaxDecode filter\n");
2087  return s;
2088}
2089
2090GBool CCITTFaxStream::isBinary(GBool last) {
2091  return str->isBinary(gTrue);
2092}
2093
2094#ifndef ENABLE_LIBJPEG
2095
2096//------------------------------------------------------------------------
2097// DCTStream
2098//------------------------------------------------------------------------
2099
2100// IDCT constants (20.12 fixed point format)
2101#define dctCos1    4017         // cos(pi/16)
2102#define dctSin1     799         // sin(pi/16)
2103#define dctCos3    3406         // cos(3*pi/16)
2104#define dctSin3    2276         // sin(3*pi/16)
2105#define dctCos6    1567         // cos(6*pi/16)
2106#define dctSin6    3784         // sin(6*pi/16)
2107#define dctSqrt2   5793         // sqrt(2)
2108#define dctSqrt1d2 2896         // sqrt(2) / 2
2109
2110// color conversion parameters (16.16 fixed point format)
2111#define dctCrToR   91881        //  1.4020
2112#define dctCbToG  -22553        // -0.3441363
2113#define dctCrToG  -46802        // -0.71413636
2114#define dctCbToB  116130        //  1.772
2115
2116// clip [-256,511] --> [0,255]
2117#define dctClipOffset 256
2118static Guchar dctClip[768];
2119static int dctClipInit = 0;
2120
2121// zig zag decode map
2122static const int dctZigZag[64] = {
2123   0,
2124   1,  8,
2125  16,  9,  2,
2126   3, 10, 17, 24,
2127  32, 25, 18, 11, 4,
2128   5, 12, 19, 26, 33, 40,
2129  48, 41, 34, 27, 20, 13,  6,
2130   7, 14, 21, 28, 35, 42, 49, 56,
2131  57, 50, 43, 36, 29, 22, 15,
2132  23, 30, 37, 44, 51, 58,
2133  59, 52, 45, 38, 31,
2134  39, 46, 53, 60,
2135  61, 54, 47,
2136  55, 62,
2137  63
2138};
2139
2140DCTStream::DCTStream(Stream *strA, int colorXformA):
2141    FilterStream(strA) {
2142  int i, j;
2143
2144  colorXform = colorXformA;
2145  progressive = interleaved = gFalse;
2146  width = height = 0;
2147  mcuWidth = mcuHeight = 0;
2148  numComps = 0;
2149  comp = 0;
2150  x = y = dy = 0;
2151  for (i = 0; i < 4; ++i) {
2152    for (j = 0; j < 32; ++j) {
2153      rowBuf[i][j] = NULL;
2154    }
2155    frameBuf[i] = NULL;
2156  }
2157
2158  if (!dctClipInit) {
2159    for (i = -256; i < 0; ++i)
2160      dctClip[dctClipOffset + i] = 0;
2161    for (i = 0; i < 256; ++i)
2162      dctClip[dctClipOffset + i] = i;
2163    for (i = 256; i < 512; ++i)
2164      dctClip[dctClipOffset + i] = 255;
2165    dctClipInit = 1;
2166  }
2167}
2168
2169DCTStream::~DCTStream() {
2170  close();
2171  delete str;
2172}
2173
2174void DCTStream::unfilteredReset() {
2175  str->reset();
2176
2177  progressive = interleaved = gFalse;
2178  width = height = 0;
2179  numComps = 0;
2180  numQuantTables = 0;
2181  numDCHuffTables = 0;
2182  numACHuffTables = 0;
2183  gotJFIFMarker = gFalse;
2184  gotAdobeMarker = gFalse;
2185  restartInterval = 0;
2186}
2187
2188
2189void DCTStream::reset() {
2190  int i, j;
2191
2192  unfilteredReset();
2193
2194  if (!readHeader()) {
2195    y = height;
2196    return;
2197  }
2198
2199  // compute MCU size
2200  if (numComps == 1) {
2201    compInfo[0].hSample = compInfo[0].vSample = 1;
2202  }
2203  mcuWidth = compInfo[0].hSample;
2204  mcuHeight = compInfo[0].vSample;
2205  for (i = 1; i < numComps; ++i) {
2206    if (compInfo[i].hSample > mcuWidth) {
2207      mcuWidth = compInfo[i].hSample;
2208    }
2209    if (compInfo[i].vSample > mcuHeight) {
2210      mcuHeight = compInfo[i].vSample;
2211    }
2212  }
2213  mcuWidth *= 8;
2214  mcuHeight *= 8;
2215
2216  // figure out color transform
2217  if (colorXform == -1) {
2218    if (numComps == 3) {
2219      if (gotJFIFMarker) {
2220        colorXform = 1;
2221      } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
2222                 compInfo[2].id == 66) { // ASCII "RGB"
2223        colorXform = 0;
2224      } else {
2225        colorXform = 1;
2226      }
2227    } else {
2228      colorXform = 0;
2229    }
2230  }
2231
2232  if (progressive || !interleaved) {
2233
2234    // allocate a buffer for the whole image
2235    bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2236    bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
2237    if (bufWidth <= 0 || bufHeight <= 0 ||
2238        bufWidth > INT_MAX / bufWidth / (int)sizeof(int)) {
2239      error(getPos(), "Invalid image size in DCT stream");
2240      y = height;
2241      return;
2242    }
2243    for (i = 0; i < numComps; ++i) {
2244      frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int));
2245      memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
2246    }
2247
2248    // read the image data
2249    do {
2250      restartMarker = 0xd0;
2251      restart();
2252      readScan();
2253    } while (readHeader());
2254
2255    // decode
2256    decodeImage();
2257
2258    // initialize counters
2259    comp = 0;
2260    x = 0;
2261    y = 0;
2262
2263  } else {
2264
2265    // allocate a buffer for one row of MCUs
2266    bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2267    for (i = 0; i < numComps; ++i) {
2268      for (j = 0; j < mcuHeight; ++j) {
2269        rowBuf[i][j] = (Guchar *)gmallocn(bufWidth, sizeof(Guchar));
2270      }
2271    }
2272
2273    // initialize counters
2274    comp = 0;
2275    x = 0;
2276    y = 0;
2277    dy = mcuHeight;
2278
2279    restartMarker = 0xd0;
2280    restart();
2281  }
2282}
2283
2284void DCTStream::close() {
2285  int i, j;
2286
2287  for (i = 0; i < 4; ++i) {
2288    for (j = 0; j < 32; ++j) {
2289      gfree(rowBuf[i][j]);
2290      rowBuf[i][j] = NULL;
2291    }
2292    gfree(frameBuf[i]);
2293    frameBuf[i] = NULL;
2294  }
2295  FilterStream::close();
2296}
2297
2298int DCTStream::getChar() {
2299  int c;
2300
2301  if (y >= height) {
2302    return EOF;
2303  }
2304  if (progressive || !interleaved) {
2305    c = frameBuf[comp][y * bufWidth + x];
2306    if (++comp == numComps) {
2307      comp = 0;
2308      if (++x == width) {
2309        x = 0;
2310        ++y;
2311      }
2312    }
2313  } else {
2314    if (dy >= mcuHeight) {
2315      if (!readMCURow()) {
2316        y = height;
2317        return EOF;
2318      }
2319      comp = 0;
2320      x = 0;
2321      dy = 0;
2322    }
2323    c = rowBuf[comp][dy][x];
2324    if (++comp == numComps) {
2325      comp = 0;
2326      if (++x == width) {
2327        x = 0;
2328        ++y;
2329        ++dy;
2330        if (y == height) {
2331          readTrailer();
2332        }
2333      }
2334    }
2335  }
2336  return c;
2337}
2338
2339int DCTStream::lookChar() {
2340  if (y >= height) {
2341    return EOF;
2342  }
2343  if (progressive || !interleaved) {
2344    return frameBuf[comp][y * bufWidth + x];
2345  } else {
2346    if (dy >= mcuHeight) {
2347      if (!readMCURow()) {
2348        y = height;
2349        return EOF;
2350      }
2351      comp = 0;
2352      x = 0;
2353      dy = 0;
2354    }
2355    return rowBuf[comp][dy][x];
2356  }
2357}
2358
2359void DCTStream::restart() {
2360  int i;
2361
2362  inputBits = 0;
2363  restartCtr = restartInterval;
2364  for (i = 0; i < numComps; ++i) {
2365    compInfo[i].prevDC = 0;
2366  }
2367  eobRun = 0;
2368}
2369
2370// Read one row of MCUs from a sequential JPEG stream.
2371GBool DCTStream::readMCURow() {
2372  int data1[64];
2373  Guchar data2[64];
2374  Guchar *p1, *p2;
2375  int pY, pCb, pCr, pR, pG, pB;
2376  int h, v, horiz, vert, hSub, vSub;
2377  int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2378  int c;
2379
2380  for (x1 = 0; x1 < width; x1 += mcuWidth) {
2381
2382    // deal with restart marker
2383    if (restartInterval > 0 && restartCtr == 0) {
2384      c = readMarker();
2385      if (c != restartMarker) {
2386        error(getPos(), "Bad DCT data: incorrect restart marker");
2387        return gFalse;
2388      }
2389      if (++restartMarker == 0xd8)
2390        restartMarker = 0xd0;
2391      restart();
2392    }
2393
2394    // read one MCU
2395    for (cc = 0; cc < numComps; ++cc) {
2396      h = compInfo[cc].hSample;
2397      v = compInfo[cc].vSample;
2398      horiz = mcuWidth / h;
2399      vert = mcuHeight / v;
2400      hSub = horiz / 8;
2401      vSub = vert / 8;
2402      for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2403        for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2404          if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2405                            &acHuffTables[scanInfo.acHuffTable[cc]],
2406                            &compInfo[cc].prevDC,
2407                            data1)) {
2408            return gFalse;
2409          }
2410          transformDataUnit(quantTables[compInfo[cc].quantTable],
2411                            data1, data2);
2412          if (hSub == 1 && vSub == 1) {
2413            for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2414              p1 = &rowBuf[cc][y2+y3][x1+x2];
2415              p1[0] = data2[i];
2416              p1[1] = data2[i+1];
2417              p1[2] = data2[i+2];
2418              p1[3] = data2[i+3];
2419              p1[4] = data2[i+4];
2420              p1[5] = data2[i+5];
2421              p1[6] = data2[i+6];
2422              p1[7] = data2[i+7];
2423            }
2424          } else if (hSub == 2 && vSub == 2) {
2425            for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2426              p1 = &rowBuf[cc][y2+y3][x1+x2];
2427              p2 = &rowBuf[cc][y2+y3+1][x1+x2];
2428              p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
2429              p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
2430              p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
2431              p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
2432              p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
2433              p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
2434              p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
2435              p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
2436            }
2437          } else {
2438            i = 0;
2439            for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2440              for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2441                for (y5 = 0; y5 < vSub; ++y5)
2442                  for (x5 = 0; x5 < hSub; ++x5)
2443                    rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
2444                ++i;
2445              }
2446            }
2447          }
2448        }
2449      }
2450    }
2451    --restartCtr;
2452
2453    // color space conversion
2454    if (colorXform) {
2455      // convert YCbCr to RGB
2456      if (numComps == 3) {
2457        for (y2 = 0; y2 < mcuHeight; ++y2) {
2458          for (x2 = 0; x2 < mcuWidth; ++x2) {
2459            pY = rowBuf[0][y2][x1+x2];
2460            pCb = rowBuf[1][y2][x1+x2] - 128;
2461            pCr = rowBuf[2][y2][x1+x2] - 128;
2462            pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2463            rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
2464            pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2465            rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
2466            pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2467            rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
2468          }
2469        }
2470      // convert YCbCrK to CMYK (K is passed through unchanged)
2471      } else if (numComps == 4) {
2472        for (y2 = 0; y2 < mcuHeight; ++y2) {
2473          for (x2 = 0; x2 < mcuWidth; ++x2) {
2474            pY = rowBuf[0][y2][x1+x2];
2475            pCb = rowBuf[1][y2][x1+x2] - 128;
2476            pCr = rowBuf[2][y2][x1+x2] - 128;
2477            pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2478            rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
2479            pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2480            rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
2481            pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2482            rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
2483          }
2484        }
2485      }
2486    }
2487  }
2488  return gTrue;
2489}
2490
2491// Read one scan from a progressive or non-interleaved JPEG stream.
2492void DCTStream::readScan() {
2493  int data[64];
2494  int x1, y1, dx1, dy1, x2, y2, y3, cc, i;
2495  int h, v, horiz, vert, vSub;
2496  int *p1;
2497  int c;
2498
2499  if (scanInfo.numComps == 1) {
2500    for (cc = 0; cc < numComps; ++cc) {
2501      if (scanInfo.comp[cc]) {
2502        break;
2503      }
2504    }
2505    dx1 = mcuWidth / compInfo[cc].hSample;
2506    dy1 = mcuHeight / compInfo[cc].vSample;
2507  } else {
2508    dx1 = mcuWidth;
2509    dy1 = mcuHeight;
2510  }
2511
2512  for (y1 = 0; y1 < height; y1 += dy1) {
2513    for (x1 = 0; x1 < width; x1 += dx1) {
2514
2515      // deal with restart marker
2516      if (restartInterval > 0 && restartCtr == 0) {
2517        c = readMarker();
2518        if (c != restartMarker) {
2519          error(getPos(), "Bad DCT data: incorrect restart marker");
2520          return;
2521        }
2522        if (++restartMarker == 0xd8) {
2523          restartMarker = 0xd0;
2524        }
2525        restart();
2526      }
2527
2528      // read one MCU
2529      for (cc = 0; cc < numComps; ++cc) {
2530        if (!scanInfo.comp[cc]) {
2531          continue;
2532        }
2533
2534        h = compInfo[cc].hSample;
2535        v = compInfo[cc].vSample;
2536        horiz = mcuWidth / h;
2537        vert = mcuHeight / v;
2538        vSub = vert / 8;
2539        for (y2 = 0; y2 < dy1; y2 += vert) {
2540          for (x2 = 0; x2 < dx1; x2 += horiz) {
2541
2542            // pull out the current values
2543            p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2544            for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2545              data[i] = p1[0];
2546              data[i+1] = p1[1];
2547              data[i+2] = p1[2];
2548              data[i+3] = p1[3];
2549              data[i+4] = p1[4];
2550              data[i+5] = p1[5];
2551              data[i+6] = p1[6];
2552              data[i+7] = p1[7];
2553              p1 += bufWidth * vSub;
2554            }
2555
2556            // read one data unit
2557            if (progressive) {
2558              if (!readProgressiveDataUnit(
2559                       &dcHuffTables[scanInfo.dcHuffTable[cc]],
2560                       &acHuffTables[scanInfo.acHuffTable[cc]],
2561                       &compInfo[cc].prevDC,
2562                       data)) {
2563                return;
2564              }
2565            } else {
2566              if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2567                                &acHuffTables[scanInfo.acHuffTable[cc]],
2568                                &compInfo[cc].prevDC,
2569                                data)) {
2570                return;
2571              }
2572            }
2573
2574            // add the data unit into frameBuf
2575            p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2576            for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2577              p1[0] = data[i];
2578              p1[1] = data[i+1];
2579              p1[2] = data[i+2];
2580              p1[3] = data[i+3];
2581              p1[4] = data[i+4];
2582              p1[5] = data[i+5];
2583              p1[6] = data[i+6];
2584              p1[7] = data[i+7];
2585              p1 += bufWidth * vSub;
2586            }
2587          }
2588        }
2589      }
2590      --restartCtr;
2591    }
2592  }
2593}
2594
2595// Read one data unit from a sequential JPEG stream.
2596GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2597                              DCTHuffTable *acHuffTable,
2598                              int *prevDC, int data[64]) {
2599  int run, size, amp;
2600  int c;
2601  int i, j;
2602
2603  if ((size = readHuffSym(dcHuffTable)) == 9999) {
2604    return gFalse;
2605  }
2606  if (size > 0) {
2607    if ((amp = readAmp(size)) == 9999) {
2608      return gFalse;
2609    }
2610  } else {
2611    amp = 0;
2612  }
2613  data[0] = *prevDC += amp;
2614  for (i = 1; i < 64; ++i) {
2615    data[i] = 0;
2616  }
2617  i = 1;
2618  while (i < 64) {
2619    run = 0;
2620    while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
2621      run += 0x10;
2622    }
2623    if (c == 9999) {
2624      return gFalse;
2625    }
2626    if (c == 0x00) {
2627      break;
2628    } else {
2629      run += (c >> 4) & 0x0f;
2630      size = c & 0x0f;
2631      amp = readAmp(size);
2632      if (amp == 9999) {
2633        return gFalse;
2634      }
2635      i += run;
2636      if (i < 64) {
2637        j = dctZigZag[i++];
2638        data[j] = amp;
2639      }
2640    }
2641  }
2642  return gTrue;
2643}
2644
2645// Read one data unit from a sequential JPEG stream.
2646GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
2647                                         DCTHuffTable *acHuffTable,
2648                                         int *prevDC, int data[64]) {
2649  int run, size, amp, bit, c;
2650  int i, j, k;
2651
2652  // get the DC coefficient
2653  i = scanInfo.firstCoeff;
2654  if (i == 0) {
2655    if (scanInfo.ah == 0) {
2656      if ((size = readHuffSym(dcHuffTable)) == 9999) {
2657        return gFalse;
2658      }
2659      if (size > 0) {
2660        if ((amp = readAmp(size)) == 9999) {
2661          return gFalse;
2662        }
2663      } else {
2664        amp = 0;
2665      }
2666      data[0] += (*prevDC += amp) << scanInfo.al;
2667    } else {
2668      if ((bit = readBit()) == 9999) {
2669        return gFalse;
2670      }
2671      data[0] += bit << scanInfo.al;
2672    }
2673    ++i;
2674  }
2675  if (scanInfo.lastCoeff == 0) {
2676    return gTrue;
2677  }
2678
2679  // check for an EOB run
2680  if (eobRun > 0) {
2681    while (i <= scanInfo.lastCoeff) {
2682      j = dctZigZag[i++];
2683      if (data[j] != 0) {
2684        if ((bit = readBit()) == EOF) {
2685          return gFalse;
2686        }
2687        if (bit) {
2688          data[j] += 1 << scanInfo.al;
2689        }
2690      }
2691    }
2692    --eobRun;
2693    return gTrue;
2694  }
2695
2696  // read the AC coefficients
2697  while (i <= scanInfo.lastCoeff) {
2698    if ((c = readHuffSym(acHuffTable)) == 9999) {
2699      return gFalse;
2700    }
2701
2702    // ZRL
2703    if (c == 0xf0) {
2704      k = 0;
2705      while (k < 16) {
2706        j = dctZigZag[i++];
2707        if (data[j] == 0) {
2708          ++k;
2709        } else {
2710          if ((bit = readBit()) == EOF) {
2711            return gFalse;
2712          }
2713          if (bit) {
2714            data[j] += 1 << scanInfo.al;
2715          }
2716        }
2717      }
2718
2719    // EOB run
2720    } else if ((c & 0x0f) == 0x00) {
2721      j = c >> 4;
2722      eobRun = 0;
2723      for (k = 0; k < j; ++k) {
2724        if ((bit = readBit()) == EOF) {
2725          return gFalse;
2726        }
2727        eobRun = (eobRun << 1) | bit;
2728      }
2729      eobRun += 1 << j;
2730      while (i <= scanInfo.lastCoeff) {
2731        j = dctZigZag[i++];
2732        if (data[j] != 0) {
2733          if ((bit = readBit()) == EOF) {
2734            return gFalse;
2735          }
2736          if (bit) {
2737            data[j] += 1 << scanInfo.al;
2738          }
2739        }
2740      }
2741      --eobRun;
2742      break;
2743
2744    // zero run and one AC coefficient
2745    } else {
2746      run = (c >> 4) & 0x0f;
2747      size = c & 0x0f;
2748      if ((amp = readAmp(size)) == 9999) {
2749        return gFalse;
2750      }
2751      k = 0;
2752      do {
2753        j = dctZigZag[i++];
2754        while (data[j] != 0) {
2755          if ((bit = readBit()) == EOF) {
2756            return gFalse;
2757          }
2758          if (bit) {
2759            data[j] += 1 << scanInfo.al;
2760          }
2761          j = dctZigZag[i++];
2762        }
2763        ++k;
2764      } while (k <= run);
2765      data[j] = amp << scanInfo.al;
2766    }
2767  }
2768
2769  return gTrue;
2770}
2771
2772// Decode a progressive JPEG image.
2773void DCTStream::decodeImage() {
2774  int dataIn[64];
2775  Guchar dataOut[64];
2776  Gushort *quantTable;
2777  int pY, pCb, pCr, pR, pG, pB;
2778  int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2779  int h, v, horiz, vert, hSub, vSub;
2780  int *p0, *p1, *p2;
2781
2782  for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
2783    for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
2784      for (cc = 0; cc < numComps; ++cc) {
2785        quantTable = quantTables[compInfo[cc].quantTable];
2786        h = compInfo[cc].hSample;
2787        v = compInfo[cc].vSample;
2788        horiz = mcuWidth / h;
2789        vert = mcuHeight / v;
2790        hSub = horiz / 8;
2791        vSub = vert / 8;
2792        for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2793          for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2794
2795            // pull out the coded data unit
2796            p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2797            for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2798              dataIn[i]   = p1[0];
2799              dataIn[i+1] = p1[1];
2800              dataIn[i+2] = p1[2];
2801              dataIn[i+3] = p1[3];
2802              dataIn[i+4] = p1[4];
2803              dataIn[i+5] = p1[5];
2804              dataIn[i+6] = p1[6];
2805              dataIn[i+7] = p1[7];
2806              p1 += bufWidth * vSub;
2807            }
2808
2809            // transform
2810            transformDataUnit(quantTable, dataIn, dataOut);
2811
2812            // store back into frameBuf, doing replication for
2813            // subsampled components
2814            p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2815            if (hSub == 1 && vSub == 1) {
2816              for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2817                p1[0] = dataOut[i] & 0xff;
2818                p1[1] = dataOut[i+1] & 0xff;
2819                p1[2] = dataOut[i+2] & 0xff;
2820                p1[3] = dataOut[i+3] & 0xff;
2821                p1[4] = dataOut[i+4] & 0xff;
2822                p1[5] = dataOut[i+5] & 0xff;
2823                p1[6] = dataOut[i+6] & 0xff;
2824                p1[7] = dataOut[i+7] & 0xff;
2825                p1 += bufWidth;
2826              }
2827            } else if (hSub == 2 && vSub == 2) {
2828              p2 = p1 + bufWidth;
2829              for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2830                p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
2831                p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
2832                p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
2833                p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
2834                p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
2835                p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
2836                p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
2837                p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
2838                p1 += bufWidth * 2;
2839                p2 += bufWidth * 2;
2840              }
2841            } else {
2842              i = 0;
2843              for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2844                for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2845                  p2 = p1 + x4;
2846                  for (y5 = 0; y5 < vSub; ++y5) {
2847                    for (x5 = 0; x5 < hSub; ++x5) {
2848                      p2[x5] = dataOut[i] & 0xff;
2849                    }
2850                    p2 += bufWidth;
2851                  }
2852                  ++i;
2853                }
2854                p1 += bufWidth * vSub;
2855              }
2856            }
2857          }
2858        }
2859      }
2860
2861      // color space conversion
2862      if (colorXform) {
2863        // convert YCbCr to RGB
2864        if (numComps == 3) {
2865          for (y2 = 0; y2 < mcuHeight; ++y2) {
2866            p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2867            p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2868            p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2869            for (x2 = 0; x2 < mcuWidth; ++x2) {
2870              pY = *p0;
2871              pCb = *p1 - 128;
2872              pCr = *p2 - 128;
2873              pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2874              *p0++ = dctClip[dctClipOffset + pR];
2875              pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2876                    32768) >> 16;
2877              *p1++ = dctClip[dctClipOffset + pG];
2878              pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2879              *p2++ = dctClip[dctClipOffset + pB];
2880            }
2881          }
2882        // convert YCbCrK to CMYK (K is passed through unchanged)
2883        } else if (numComps == 4) {
2884          for (y2 = 0; y2 < mcuHeight; ++y2) {
2885            p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2886            p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2887            p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2888            for (x2 = 0; x2 < mcuWidth; ++x2) {
2889              pY = *p0;
2890              pCb = *p1 - 128;
2891              pCr = *p2 - 128;
2892              pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2893              *p0++ = 255 - dctClip[dctClipOffset + pR];
2894              pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2895                    32768) >> 16;
2896              *p1++ = 255 - dctClip[dctClipOffset + pG];
2897              pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2898              *p2++ = 255 - dctClip[dctClipOffset + pB];
2899            }
2900          }
2901        }
2902      }
2903    }
2904  }
2905}
2906
2907// Transform one data unit -- this performs the dequantization and
2908// IDCT steps.  This IDCT algorithm is taken from:
2909//   Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2910//   "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2911//   IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2912//   988-991.
2913// The stage numbers mentioned in the comments refer to Figure 1 in this
2914// paper.
2915void DCTStream::transformDataUnit(Gushort *quantTable,
2916                                  int dataIn[64], Guchar dataOut[64]) {
2917  int v0, v1, v2, v3, v4, v5, v6, v7, t;
2918  int *p;
2919  int i;
2920
2921  // dequant
2922  for (i = 0; i < 64; ++i) {
2923    dataIn[i] *= quantTable[i];
2924  }
2925
2926  // inverse DCT on rows
2927  for (i = 0; i < 64; i += 8) {
2928    p = dataIn + i;
2929
2930    // check for all-zero AC coefficients
2931    if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
2932        p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
2933      t = (dctSqrt2 * p[0] + 512) >> 10;
2934      p[0] = t;
2935      p[1] = t;
2936      p[2] = t;
2937      p[3] = t;
2938      p[4] = t;
2939      p[5] = t;
2940      p[6] = t;
2941      p[7] = t;
2942      continue;
2943    }
2944
2945    // stage 4
2946    v0 = (dctSqrt2 * p[0] + 128) >> 8;
2947    v1 = (dctSqrt2 * p[4] + 128) >> 8;
2948    v2 = p[2];
2949    v3 = p[6];
2950    v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
2951    v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
2952    v5 = p[3] << 4;
2953    v6 = p[5] << 4;
2954
2955    // stage 3
2956    t = (v0 - v1+ 1) >> 1;
2957    v0 = (v0 + v1 + 1) >> 1;
2958    v1 = t;
2959    t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
2960    v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2961    v3 = t;
2962    t = (v4 - v6 + 1) >> 1;
2963    v4 = (v4 + v6 + 1) >> 1;
2964    v6 = t;
2965    t = (v7 + v5 + 1) >> 1;
2966    v5 = (v7 - v5 + 1) >> 1;
2967    v7 = t;
2968
2969    // stage 2
2970    t = (v0 - v3 + 1) >> 1;
2971    v0 = (v0 + v3 + 1) >> 1;
2972    v3 = t;
2973    t = (v1 - v2 + 1) >> 1;
2974    v1 = (v1 + v2 + 1) >> 1;
2975    v2 = t;
2976    t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2977    v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2978    v7 = t;
2979    t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2980    v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2981    v6 = t;
2982
2983    // stage 1
2984    p[0] = v0 + v7;
2985    p[7] = v0 - v7;
2986    p[1] = v1 + v6;
2987    p[6] = v1 - v6;
2988    p[2] = v2 + v5;
2989    p[5] = v2 - v5;
2990    p[3] = v3 + v4;
2991    p[4] = v3 - v4;
2992  }
2993
2994  // inverse DCT on columns
2995  for (i = 0; i < 8; ++i) {
2996    p = dataIn + i;
2997
2998    // check for all-zero AC coefficients
2999    if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
3000        p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
3001      t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
3002      p[0*8] = t;
3003      p[1*8] = t;
3004      p[2*8] = t;
3005      p[3*8] = t;
3006      p[4*8] = t;
3007      p[5*8] = t;
3008      p[6*8] = t;
3009      p[7*8] = t;
3010      continue;
3011    }
3012
3013    // stage 4
3014    v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
3015    v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
3016    v2 = p[2*8];
3017    v3 = p[6*8];
3018    v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
3019    v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
3020    v5 = p[3*8];
3021    v6 = p[5*8];
3022
3023    // stage 3
3024    t = (v0 - v1 + 1) >> 1;
3025    v0 = (v0 + v1 + 1) >> 1;
3026    v1 = t;
3027    t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
3028    v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
3029    v3 = t;
3030    t = (v4 - v6 + 1) >> 1;
3031    v4 = (v4 + v6 + 1) >> 1;
3032    v6 = t;
3033    t = (v7 + v5 + 1) >> 1;
3034    v5 = (v7 - v5 + 1) >> 1;
3035    v7 = t;
3036
3037    // stage 2
3038    t = (v0 - v3 + 1) >> 1;
3039    v0 = (v0 + v3 + 1) >> 1;
3040    v3 = t;
3041    t = (v1 - v2 + 1) >> 1;
3042    v1 = (v1 + v2 + 1) >> 1;
3043    v2 = t;
3044    t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
3045    v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
3046    v7 = t;
3047    t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
3048    v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
3049    v6 = t;
3050
3051    // stage 1
3052    p[0*8] = v0 + v7;
3053    p[7*8] = v0 - v7;
3054    p[1*8] = v1 + v6;
3055    p[6*8] = v1 - v6;
3056    p[2*8] = v2 + v5;
3057    p[5*8] = v2 - v5;
3058    p[3*8] = v3 + v4;
3059    p[4*8] = v3 - v4;
3060  }
3061
3062  // convert to 8-bit integers
3063  for (i = 0; i < 64; ++i) {
3064    dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
3065  }
3066}
3067
3068int DCTStream::readHuffSym(DCTHuffTable *table) {
3069  Gushort code;
3070  int bit;
3071  int codeBits;
3072
3073  code = 0;
3074  codeBits = 0;
3075  do {
3076    // add a bit to the code
3077    if ((bit = readBit()) == EOF)
3078      return 9999;
3079    code = (code << 1) + bit;
3080    ++codeBits;
3081
3082    // look up code
3083    if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
3084      code -= table->firstCode[codeBits];
3085      return table->sym[table->firstSym[codeBits] + code];
3086    }
3087  } while (codeBits < 16);
3088
3089  error(getPos(), "Bad Huffman code in DCT stream");
3090  return 9999;
3091}
3092
3093int DCTStream::readAmp(int size) {
3094  int amp, bit;
3095  int bits;
3096
3097  amp = 0;
3098  for (bits = 0; bits < size; ++bits) {
3099    if ((bit = readBit()) == EOF)
3100      return 9999;
3101    amp = (amp << 1) + bit;
3102  }
3103  if (amp < (1 << (size - 1)))
3104    amp -= (1 << size) - 1;
3105  return amp;
3106}
3107
3108int DCTStream::readBit() {
3109  int bit;
3110  int c, c2;
3111
3112  if (inputBits == 0) {
3113    if ((c = str->getChar()) == EOF)
3114      return EOF;
3115    if (c == 0xff) {
3116      do {
3117        c2 = str->getChar();
3118      } while (c2 == 0xff);
3119      if (c2 != 0x00) {
3120        error(getPos(), "Bad DCT data: missing 00 after ff");
3121        return EOF;
3122      }
3123    }
3124    inputBuf = c;
3125    inputBits = 8;
3126  }
3127  bit = (inputBuf >> (inputBits - 1)) & 1;
3128  --inputBits;
3129  return bit;
3130}
3131
3132GBool DCTStream::readHeader() {
3133  GBool doScan;
3134  int n;
3135  int c = 0;
3136  int i;
3137
3138  // read headers
3139  doScan = gFalse;
3140  while (!doScan) {
3141    c = readMarker();
3142    switch (c) {
3143    case 0xc0:                  // SOF0 (sequential)
3144    case 0xc1:                  // SOF1 (extended sequential)
3145      if (!readBaselineSOF()) {
3146        return gFalse;
3147      }
3148      break;
3149    case 0xc2:                  // SOF2 (progressive)
3150      if (!readProgressiveSOF()) {
3151        return gFalse;
3152      }
3153      break;
3154    case 0xc4:                  // DHT
3155      if (!readHuffmanTables()) {
3156        return gFalse;
3157      }
3158      break;
3159    case 0xd8:                  // SOI
3160      break;
3161    case 0xd9:                  // EOI
3162      return gFalse;
3163    case 0xda:                  // SOS
3164      if (!readScanInfo()) {
3165        return gFalse;
3166      }
3167      doScan = gTrue;
3168      break;
3169    case 0xdb:                  // DQT
3170      if (!readQuantTables()) {
3171        return gFalse;
3172      }
3173      break;
3174    case 0xdd:                  // DRI
3175      if (!readRestartInterval()) {
3176        return gFalse;
3177      }
3178      break;
3179    case 0xe0:                  // APP0
3180      if (!readJFIFMarker()) {
3181        return gFalse;
3182      }
3183      break;
3184    case 0xee:                  // APP14
3185      if (!readAdobeMarker()) {
3186        return gFalse;
3187      }
3188      break;
3189    case EOF:
3190      error(getPos(), "Bad DCT header");
3191      return gFalse;
3192    default:
3193      // skip APPn / COM / etc.
3194      if (c >= 0xe0) {
3195        n = read16() - 2;
3196        for (i = 0; i < n; ++i) {
3197          str->getChar();
3198        }
3199      } else {
3200        error(getPos(), "Unknown DCT marker <%02x>", c);
3201        return gFalse;
3202      }
3203      break;
3204    }
3205  }
3206
3207  return gTrue;
3208}
3209
3210GBool DCTStream::readBaselineSOF() {
3211  int length;
3212  int prec;
3213  int i;
3214  int c;
3215
3216  length = read16();
3217  prec = str->getChar();
3218  height = read16();
3219  width = read16();
3220  numComps = str->getChar();
3221  if (numComps <= 0 || numComps > 4) {
3222    error(getPos(), "Bad number of components in DCT stream");
3223    numComps = 0;
3224    return gFalse;
3225  }
3226  if (prec != 8) {
3227    error(getPos(), "Bad DCT precision %d", prec);
3228    return gFalse;
3229  }
3230  for (i = 0; i < numComps; ++i) {
3231    compInfo[i].id = str->getChar();
3232    c = str->getChar();
3233    compInfo[i].hSample = (c >> 4) & 0x0f;
3234    compInfo[i].vSample = c & 0x0f;
3235    compInfo[i].quantTable = str->getChar();
3236  }
3237  progressive = gFalse;
3238  return gTrue;
3239}
3240
3241GBool DCTStream::readProgressiveSOF() {
3242  int length;
3243  int prec;
3244  int i;
3245  int c;
3246
3247  length = read16();
3248  prec = str->getChar();
3249  height = read16();
3250  width = read16();
3251  numComps = str->getChar();
3252  if (prec != 8) {
3253    error(getPos(), "Bad DCT precision %d", prec);
3254    return gFalse;
3255  }
3256  for (i = 0; i < numComps; ++i) {
3257    compInfo[i].id = str->getChar();
3258    c = str->getChar();
3259    compInfo[i].hSample = (c >> 4) & 0x0f;
3260    compInfo[i].vSample = c & 0x0f;
3261    compInfo[i].quantTable = str->getChar();
3262  }
3263  progressive = gTrue;
3264  return gTrue;
3265}
3266
3267GBool DCTStream::readScanInfo() {
3268  int length;
3269  int id, c;
3270  int i, j;
3271
3272  length = read16() - 2;
3273  scanInfo.numComps = str->getChar();
3274  if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) {
3275    error(getPos(), "Bad number of components in DCT stream");
3276    scanInfo.numComps = 0;
3277    return gFalse;
3278  }
3279  --length;
3280  if (length != 2 * scanInfo.numComps + 3) {
3281    error(getPos(), "Bad DCT scan info block");
3282    return gFalse;
3283  }
3284  interleaved = scanInfo.numComps == numComps;
3285  for (j = 0; j < numComps; ++j) {
3286    scanInfo.comp[j] = gFalse;
3287  }
3288  for (i = 0; i < scanInfo.numComps; ++i) {
3289    id = str->getChar();
3290    // some (broken) DCT streams reuse ID numbers, but at least they
3291    // keep the components in order, so we check compInfo[i] first to
3292    // work around the problem
3293    if (id == compInfo[i].id) {
3294      j = i;
3295    } else {
3296      for (j = 0; j < numComps; ++j) {
3297        if (id == compInfo[j].id) {
3298          break;
3299        }
3300      }
3301      if (j == numComps) {
3302        error(getPos(), "Bad DCT component ID in scan info block");
3303        return gFalse;
3304      }
3305    }
3306    scanInfo.comp[j] = gTrue;
3307    c = str->getChar();
3308    scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
3309    scanInfo.acHuffTable[j] = c & 0x0f;
3310  }
3311  scanInfo.firstCoeff = str->getChar();
3312  scanInfo.lastCoeff = str->getChar();
3313  if (scanInfo.firstCoeff < 0 || scanInfo.lastCoeff > 63 ||
3314      scanInfo.firstCoeff > scanInfo.lastCoeff) {
3315    error(getPos(), "Bad DCT coefficient numbers in scan info block");
3316    return gFalse;
3317  }
3318  c = str->getChar();
3319  scanInfo.ah = (c >> 4) & 0x0f;
3320  scanInfo.al = c & 0x0f;
3321  return gTrue;
3322}
3323
3324GBool DCTStream::readQuantTables() {
3325  int length, prec, i, index;
3326
3327  length = read16() - 2;
3328  while (length > 0) {
3329    index = str->getChar();
3330    prec = (index >> 4) & 0x0f;
3331    index &= 0x0f;
3332    if (prec > 1 || index >= 4) {
3333      error(getPos(), "Bad DCT quantization table");
3334      return gFalse;
3335    }
3336    if (index == numQuantTables) {
3337      numQuantTables = index + 1;
3338    }
3339    for (i = 0; i < 64; ++i) {
3340      if (prec) {
3341        quantTables[index][dctZigZag[i]] = read16();
3342      } else {
3343        quantTables[index][dctZigZag[i]] = str->getChar();
3344      }
3345    }
3346    if (prec) {
3347      length -= 129;
3348    } else {
3349      length -= 65;
3350    }
3351  }
3352  return gTrue;
3353}
3354
3355GBool DCTStream::readHuffmanTables() {
3356  DCTHuffTable *tbl;
3357  int length;
3358  int index;
3359  Gushort code;
3360  Guchar sym;
3361  int i;
3362  int c;
3363
3364  length = read16() - 2;
3365  while (length > 0) {
3366    index = str->getChar();
3367    --length;
3368    if ((index & 0x0f) >= 4) {
3369      error(getPos(), "Bad DCT Huffman table");
3370      return gFalse;
3371    }
3372    if (index & 0x10) {
3373      index &= 0x0f;
3374      if (index >= numACHuffTables)
3375        numACHuffTables = index+1;
3376      tbl = &acHuffTables[index];
3377    } else {
3378      index &= 0x0f;
3379      if (index >= numDCHuffTables)
3380        numDCHuffTables = index+1;
3381      tbl = &dcHuffTables[index];
3382    }
3383    sym = 0;
3384    code = 0;
3385    for (i = 1; i <= 16; ++i) {
3386      c = str->getChar();
3387      tbl->firstSym[i] = sym;
3388      tbl->firstCode[i] = code;
3389      tbl->numCodes[i] = c;
3390      sym += c;
3391      code = (code + c) << 1;
3392    }
3393    length -= 16;
3394    for (i = 0; i < sym; ++i)
3395      tbl->sym[i] = str->getChar();
3396    length -= sym;
3397  }
3398  return gTrue;
3399}
3400
3401GBool DCTStream::readRestartInterval() {
3402  int length;
3403
3404  length = read16();
3405  if (length != 4) {
3406    error(getPos(), "Bad DCT restart interval");
3407    return gFalse;
3408  }
3409  restartInterval = read16();
3410  return gTrue;
3411}
3412
3413GBool DCTStream::readJFIFMarker() {
3414  int length, i;
3415  char buf[5];
3416  int c;
3417
3418  length = read16();
3419  length -= 2;
3420  if (length >= 5) {
3421    for (i = 0; i < 5; ++i) {
3422      if ((c = str->getChar()) == EOF) {
3423        error(getPos(), "Bad DCT APP0 marker");
3424        return gFalse;
3425      }
3426      buf[i] = c;
3427    }
3428    length -= 5;
3429    if (!memcmp(buf, "JFIF\0", 5)) {
3430      gotJFIFMarker = gTrue;
3431    }
3432  }
3433  while (length > 0) {
3434    if (str->getChar() == EOF) {
3435      error(getPos(), "Bad DCT APP0 marker");
3436      return gFalse;
3437    }
3438    --length;
3439  }
3440  return gTrue;
3441}
3442
3443GBool DCTStream::readAdobeMarker() {
3444  int length, i;
3445  char buf[12];
3446  int c;
3447
3448  length = read16();
3449  if (length < 14) {
3450    goto err;
3451  }
3452  for (i = 0; i < 12; ++i) {
3453    if ((c = str->getChar()) == EOF) {
3454      goto err;
3455    }
3456    buf[i] = c;
3457  }
3458  if (strncmp(buf, "Adobe", 5)) {
3459    goto err;
3460  }
3461  colorXform = buf[11];
3462  gotAdobeMarker = gTrue;
3463  for (i = 14; i < length; ++i) {
3464    if (str->getChar() == EOF) {
3465      goto err;
3466    }
3467  }
3468  return gTrue;
3469
3470 err:
3471  error(getPos(), "Bad DCT Adobe APP14 marker");
3472  return gFalse;
3473}
3474
3475GBool DCTStream::readTrailer() {
3476  int c;
3477
3478  c = readMarker();
3479  if (c != 0xd9) {              // EOI
3480    error(getPos(), "Bad DCT trailer");
3481    return gFalse;
3482  }
3483  return gTrue;
3484}
3485
3486int DCTStream::readMarker() {
3487  int c;
3488
3489  do {
3490    do {
3491      c = str->getChar();
3492    } while (c != 0xff && c != EOF);
3493    while (c == 0xff) {
3494      c = str->getChar();
3495    }
3496  } while (c == 0x00);
3497  return c;
3498}
3499
3500int DCTStream::read16() {
3501  int c1, c2;
3502
3503  if ((c1 = str->getChar()) == EOF)
3504    return EOF;
3505  if ((c2 = str->getChar()) == EOF)
3506    return EOF;
3507  return (c1 << 8) + c2;
3508}
3509
3510GooString *DCTStream::getPSFilter(int psLevel, char *indent) {
3511  GooString *s;
3512
3513  if (psLevel < 2) {
3514    return NULL;
3515  }
3516  if (!(s = str->getPSFilter(psLevel, indent))) {
3517    return NULL;
3518  }
3519  s->append(indent)->append("<< >> /DCTDecode filter\n");
3520  return s;
3521}
3522
3523GBool DCTStream::isBinary(GBool last) {
3524  return str->isBinary(gTrue);
3525}
3526
3527#endif
3528
3529#ifndef ENABLE_ZLIB
3530//------------------------------------------------------------------------
3531// FlateStream
3532//------------------------------------------------------------------------
3533
3534int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
3535  16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
3536};
3537
3538FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
3539  {0,   3},
3540  {0,   4},
3541  {0,   5},
3542  {0,   6},
3543  {0,   7},
3544  {0,   8},
3545  {0,   9},
3546  {0,  10},
3547  {1,  11},
3548  {1,  13},
3549  {1,  15},
3550  {1,  17},
3551  {2,  19},
3552  {2,  23},
3553  {2,  27},
3554  {2,  31},
3555  {3,  35},
3556  {3,  43},
3557  {3,  51},
3558  {3,  59},
3559  {4,  67},
3560  {4,  83},
3561  {4,  99},
3562  {4, 115},
3563  {5, 131},
3564  {5, 163},
3565  {5, 195},
3566  {5, 227},
3567  {0, 258},
3568  {0, 258},
3569  {0, 258}
3570};
3571
3572FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
3573  { 0,     1},
3574  { 0,     2},
3575  { 0,     3},
3576  { 0,     4},
3577  { 1,     5},
3578  { 1,     7},
3579  { 2,     9},
3580  { 2,    13},
3581  { 3,    17},
3582  { 3,    25},
3583  { 4,    33},
3584  { 4,    49},
3585  { 5,    65},
3586  { 5,    97},
3587  { 6,   129},
3588  { 6,   193},
3589  { 7,   257},
3590  { 7,   385},
3591  { 8,   513},
3592  { 8,   769},
3593  { 9,  1025},
3594  { 9,  1537},
3595  {10,  2049},
3596  {10,  3073},
3597  {11,  4097},
3598  {11,  6145},
3599  {12,  8193},
3600  {12, 12289},
3601  {13, 16385},
3602  {13, 24577}
3603};
3604
3605static FlateCode flateFixedLitCodeTabCodes[512] = {
3606  {7, 0x0100},
3607  {8, 0x0050},
3608  {8, 0x0010},
3609  {8, 0x0118},
3610  {7, 0x0110},
3611  {8, 0x0070},
3612  {8, 0x0030},
3613  {9, 0x00c0},
3614  {7, 0x0108},
3615  {8, 0x0060},
3616  {8, 0x0020},
3617  {9, 0x00a0},
3618  {8, 0x0000},
3619  {8, 0x0080},
3620  {8, 0x0040},
3621  {9, 0x00e0},
3622  {7, 0x0104},
3623  {8, 0x0058},
3624  {8, 0x0018},
3625  {9, 0x0090},
3626  {7, 0x0114},
3627  {8, 0x0078},
3628  {8, 0x0038},
3629  {9, 0x00d0},
3630  {7, 0x010c},
3631  {8, 0x0068},
3632  {8, 0x0028},
3633  {9, 0x00b0},
3634  {8, 0x0008},
3635  {8, 0x0088},
3636  {8, 0x0048},
3637  {9, 0x00f0},
3638  {7, 0x0102},
3639  {8, 0x0054},
3640  {8, 0x0014},
3641  {8, 0x011c},
3642  {7, 0x0112},
3643  {8, 0x0074},
3644  {8, 0x0034},
3645  {9, 0x00c8},
3646  {7, 0x010a},
3647  {8, 0x0064},
3648  {8, 0x0024},
3649  {9, 0x00a8},
3650  {8, 0x0004},
3651  {8, 0x0084},
3652  {8, 0x0044},
3653  {9, 0x00e8},
3654  {7, 0x0106},
3655  {8, 0x005c},
3656  {8, 0x001c},
3657  {9, 0x0098},
3658  {7, 0x0116},
3659  {8, 0x007c},
3660  {8, 0x003c},
3661  {9, 0x00d8},
3662  {7, 0x010e},
3663  {8, 0x006c},
3664  {8, 0x002c},
3665  {9, 0x00b8},
3666  {8, 0x000c},
3667  {8, 0x008c},
3668  {8, 0x004c},
3669  {9, 0x00f8},
3670  {7, 0x0101},
3671  {8, 0x0052},
3672  {8, 0x0012},
3673  {8, 0x011a},
3674  {7, 0x0111},
3675  {8, 0x0072},
3676  {8, 0x0032},
3677  {9, 0x00c4},
3678  {7, 0x0109},
3679  {8, 0x0062},
3680  {8, 0x0022},
3681  {9, 0x00a4},
3682  {8, 0x0002},
3683  {8, 0x0082},
3684  {8, 0x0042},
3685  {9, 0x00e4},
3686  {7, 0x0105},
3687  {8, 0x005a},
3688  {8, 0x001a},
3689  {9, 0x0094},
3690  {7, 0x0115},
3691  {8, 0x007a},
3692  {8, 0x003a},
3693  {9, 0x00d4},
3694  {7, 0x010d},
3695  {8, 0x006a},
3696  {8, 0x002a},
3697  {9, 0x00b4},
3698  {8, 0x000a},
3699  {8, 0x008a},
3700  {8, 0x004a},
3701  {9, 0x00f4},
3702  {7, 0x0103},
3703  {8, 0x0056},
3704  {8, 0x0016},
3705  {8, 0x011e},
3706  {7, 0x0113},
3707  {8, 0x0076},
3708  {8, 0x0036},
3709  {9, 0x00cc},
3710  {7, 0x010b},
3711  {8, 0x0066},
3712  {8, 0x0026},
3713  {9, 0x00ac},
3714  {8, 0x0006},
3715  {8, 0x0086},
3716  {8, 0x0046},
3717  {9, 0x00ec},
3718  {7, 0x0107},
3719  {8, 0x005e},
3720  {8, 0x001e},
3721  {9, 0x009c},
3722  {7, 0x0117},
3723  {8, 0x007e},
3724  {8, 0x003e},
3725  {9, 0x00dc},
3726  {7, 0x010f},
3727  {8, 0x006e},
3728  {8, 0x002e},
3729  {9, 0x00bc},
3730  {8, 0x000e},
3731  {8, 0x008e},
3732  {8, 0x004e},
3733  {9, 0x00fc},
3734  {7, 0x0100},
3735  {8, 0x0051},
3736  {8, 0x0011},
3737  {8, 0x0119},
3738  {7, 0x0110},
3739  {8, 0x0071},
3740  {8, 0x0031},
3741  {9, 0x00c2},
3742  {7, 0x0108},
3743  {8, 0x0061},
3744  {8, 0x0021},
3745  {9, 0x00a2},
3746  {8, 0x0001},
3747  {8, 0x0081},
3748  {8, 0x0041},
3749  {9, 0x00e2},
3750  {7, 0x0104},
3751  {8, 0x0059},
3752  {8, 0x0019},
3753  {9, 0x0092},
3754  {7, 0x0114},
3755  {8, 0x0079},
3756  {8, 0x0039},
3757  {9, 0x00d2},
3758  {7, 0x010c},
3759  {8, 0x0069},
3760  {8, 0x0029},
3761  {9, 0x00b2},
3762  {8, 0x0009},
3763  {8, 0x0089},
3764  {8, 0x0049},
3765  {9, 0x00f2},
3766  {7, 0x0102},
3767  {8, 0x0055},
3768  {8, 0x0015},
3769  {8, 0x011d},
3770  {7, 0x0112},
3771  {8, 0x0075},
3772  {8, 0x0035},
3773  {9, 0x00ca},
3774  {7, 0x010a},
3775  {8, 0x0065},
3776  {8, 0x0025},
3777  {9, 0x00aa},
3778  {8, 0x0005},
3779  {8, 0x0085},
3780  {8, 0x0045},
3781  {9, 0x00ea},
3782  {7, 0x0106},
3783  {8, 0x005d},
3784  {8, 0x001d},
3785  {9, 0x009a},
3786  {7, 0x0116},
3787  {8, 0x007d},
3788  {8, 0x003d},
3789  {9, 0x00da},
3790  {7, 0x010e},
3791  {8, 0x006d},
3792  {8, 0x002d},
3793  {9, 0x00ba},
3794  {8, 0x000d},
3795  {8, 0x008d},
3796  {8, 0x004d},
3797  {9, 0x00fa},
3798  {7, 0x0101},
3799  {8, 0x0053},
3800  {8, 0x0013},
3801  {8, 0x011b},
3802  {7, 0x0111},
3803  {8, 0x0073},
3804  {8, 0x0033},
3805  {9, 0x00c6},
3806  {7, 0x0109},
3807  {8, 0x0063},
3808  {8, 0x0023},
3809  {9, 0x00a6},
3810  {8, 0x0003},
3811  {8, 0x0083},
3812  {8, 0x0043},
3813  {9, 0x00e6},
3814  {7, 0x0105},
3815  {8, 0x005b},
3816  {8, 0x001b},
3817  {9, 0x0096},
3818  {7, 0x0115},
3819  {8, 0x007b},
3820  {8, 0x003b},
3821  {9, 0x00d6},
3822  {7, 0x010d},
3823  {8, 0x006b},
3824  {8, 0x002b},
3825  {9, 0x00b6},
3826  {8, 0x000b},
3827  {8, 0x008b},
3828  {8, 0x004b},
3829  {9, 0x00f6},
3830  {7, 0x0103},
3831  {8, 0x0057},
3832  {8, 0x0017},
3833  {8, 0x011f},
3834  {7, 0x0113},
3835  {8, 0x0077},
3836  {8, 0x0037},
3837  {9, 0x00ce},
3838  {7, 0x010b},
3839  {8, 0x0067},
3840  {8, 0x0027},
3841  {9, 0x00ae},
3842  {8, 0x0007},
3843  {8, 0x0087},
3844  {8, 0x0047},
3845  {9, 0x00ee},
3846  {7, 0x0107},
3847  {8, 0x005f},
3848  {8, 0x001f},
3849  {9, 0x009e},
3850  {7, 0x0117},
3851  {8, 0x007f},
3852  {8, 0x003f},
3853  {9, 0x00de},
3854  {7, 0x010f},
3855  {8, 0x006f},
3856  {8, 0x002f},
3857  {9, 0x00be},
3858  {8, 0x000f},
3859  {8, 0x008f},
3860  {8, 0x004f},
3861  {9, 0x00fe},
3862  {7, 0x0100},
3863  {8, 0x0050},
3864  {8, 0x0010},
3865  {8, 0x0118},
3866  {7, 0x0110},
3867  {8, 0x0070},
3868  {8, 0x0030},
3869  {9, 0x00c1},
3870  {7, 0x0108},
3871  {8, 0x0060},
3872  {8, 0x0020},
3873  {9, 0x00a1},
3874  {8, 0x0000},
3875  {8, 0x0080},
3876  {8, 0x0040},
3877  {9, 0x00e1},
3878  {7, 0x0104},
3879  {8, 0x0058},
3880  {8, 0x0018},
3881  {9, 0x0091},
3882  {7, 0x0114},
3883  {8, 0x0078},
3884  {8, 0x0038},
3885  {9, 0x00d1},
3886  {7, 0x010c},
3887  {8, 0x0068},
3888  {8, 0x0028},
3889  {9, 0x00b1},
3890  {8, 0x0008},
3891  {8, 0x0088},
3892  {8, 0x0048},
3893  {9, 0x00f1},
3894  {7, 0x0102},
3895  {8, 0x0054},
3896  {8, 0x0014},
3897  {8, 0x011c},
3898  {7, 0x0112},
3899  {8, 0x0074},
3900  {8, 0x0034},
3901  {9, 0x00c9},
3902  {7, 0x010a},
3903  {8, 0x0064},
3904  {8, 0x0024},
3905  {9, 0x00a9},
3906  {8, 0x0004},
3907  {8, 0x0084},
3908  {8, 0x0044},
3909  {9, 0x00e9},
3910  {7, 0x0106},
3911  {8, 0x005c},
3912  {8, 0x001c},
3913  {9, 0x0099},
3914  {7, 0x0116},
3915  {8, 0x007c},
3916  {8, 0x003c},
3917  {9, 0x00d9},
3918  {7, 0x010e},
3919  {8, 0x006c},
3920  {8, 0x002c},
3921  {9, 0x00b9},
3922  {8, 0x000c},
3923  {8, 0x008c},
3924  {8, 0x004c},
3925  {9, 0x00f9},
3926  {7, 0x0101},
3927  {8, 0x0052},
3928  {8, 0x0012},
3929  {8, 0x011a},
3930  {7, 0x0111},
3931  {8, 0x0072},
3932  {8, 0x0032},
3933  {9, 0x00c5},
3934  {7, 0x0109},
3935  {8, 0x0062},
3936  {8, 0x0022},
3937  {9, 0x00a5},
3938  {8, 0x0002},
3939  {8, 0x0082},
3940  {8, 0x0042},
3941  {9, 0x00e5},
3942  {7, 0x0105},
3943  {8, 0x005a},
3944  {8, 0x001a},
3945  {9, 0x0095},
3946  {7, 0x0115},
3947  {8, 0x007a},
3948  {8, 0x003a},
3949  {9, 0x00d5},
3950  {7, 0x010d},
3951  {8, 0x006a},
3952  {8, 0x002a},
3953  {9, 0x00b5},
3954  {8, 0x000a},
3955  {8, 0x008a},
3956  {8, 0x004a},
3957  {9, 0x00f5},
3958  {7, 0x0103},
3959  {8, 0x0056},
3960  {8, 0x0016},
3961  {8, 0x011e},
3962  {7, 0x0113},
3963  {8, 0x0076},
3964  {8, 0x0036},
3965  {9, 0x00cd},
3966  {7, 0x010b},
3967  {8, 0x0066},
3968  {8, 0x0026},
3969  {9, 0x00ad},
3970  {8, 0x0006},
3971  {8, 0x0086},
3972  {8, 0x0046},
3973  {9, 0x00ed},
3974  {7, 0x0107},
3975  {8, 0x005e},
3976  {8, 0x001e},
3977  {9, 0x009d},
3978  {7, 0x0117},
3979  {8, 0x007e},
3980  {8, 0x003e},
3981  {9, 0x00dd},
3982  {7, 0x010f},
3983  {8, 0x006e},
3984  {8, 0x002e},
3985  {9, 0x00bd},
3986  {8, 0x000e},
3987  {8, 0x008e},
3988  {8, 0x004e},
3989  {9, 0x00fd},
3990  {7, 0x0100},
3991  {8, 0x0051},
3992  {8, 0x0011},
3993  {8, 0x0119},
3994  {7, 0x0110},
3995  {8, 0x0071},
3996  {8, 0x0031},
3997  {9, 0x00c3},
3998  {7, 0x0108},
3999  {8, 0x0061},
4000  {8, 0x0021},
4001  {9, 0x00a3},
4002  {8, 0x0001},
4003  {8, 0x0081},
4004  {8, 0x0041},
4005  {9, 0x00e3},
4006  {7, 0x0104},
4007  {8, 0x0059},
4008  {8, 0x0019},
4009  {9, 0x0093},
4010  {7, 0x0114},
4011  {8, 0x0079},
4012  {8, 0x0039},
4013  {9, 0x00d3},
4014  {7, 0x010c},
4015  {8, 0x0069},
4016  {8, 0x0029},
4017  {9, 0x00b3},
4018  {8, 0x0009},
4019  {8, 0x0089},
4020  {8, 0x0049},
4021  {9, 0x00f3},
4022  {7, 0x0102},
4023  {8, 0x0055},
4024  {8, 0x0015},
4025  {8, 0x011d},
4026  {7, 0x0112},
4027  {8, 0x0075},
4028  {8, 0x0035},
4029  {9, 0x00cb},
4030  {7, 0x010a},
4031  {8, 0x0065},
4032  {8, 0x0025},
4033  {9, 0x00ab},
4034  {8, 0x0005},
4035  {8, 0x0085},
4036  {8, 0x0045},
4037  {9, 0x00eb},
4038  {7, 0x0106},
4039  {8, 0x005d},
4040  {8, 0x001d},
4041  {9, 0x009b},
4042  {7, 0x0116},
4043  {8, 0x007d},
4044  {8, 0x003d},
4045  {9, 0x00db},
4046  {7, 0x010e},
4047  {8, 0x006d},
4048  {8, 0x002d},
4049  {9, 0x00bb},
4050  {8, 0x000d},
4051  {8, 0x008d},
4052  {8, 0x004d},
4053  {9, 0x00fb},
4054  {7, 0x0101},
4055  {8, 0x0053},
4056  {8, 0x0013},
4057  {8, 0x011b},
4058  {7, 0x0111},
4059  {8, 0x0073},
4060  {8, 0x0033},
4061  {9, 0x00c7},
4062  {7, 0x0109},
4063  {8, 0x0063},
4064  {8, 0x0023},
4065  {9, 0x00a7},
4066  {8, 0x0003},
4067  {8, 0x0083},
4068  {8, 0x0043},
4069  {9, 0x00e7},
4070  {7, 0x0105},
4071  {8, 0x005b},
4072  {8, 0x001b},
4073  {9, 0x0097},
4074  {7, 0x0115},
4075  {8, 0x007b},
4076  {8, 0x003b},
4077  {9, 0x00d7},
4078  {7, 0x010d},
4079  {8, 0x006b},
4080  {8, 0x002b},
4081  {9, 0x00b7},
4082  {8, 0x000b},
4083  {8, 0x008b},
4084  {8, 0x004b},
4085  {9, 0x00f7},
4086  {7, 0x0103},
4087  {8, 0x0057},
4088  {8, 0x0017},
4089  {8, 0x011f},
4090  {7, 0x0113},
4091  {8, 0x0077},
4092  {8, 0x0037},
4093  {9, 0x00cf},
4094  {7, 0x010b},
4095  {8, 0x0067},
4096  {8, 0x0027},
4097  {9, 0x00af},
4098  {8, 0x0007},
4099  {8, 0x0087},
4100  {8, 0x0047},
4101  {9, 0x00ef},
4102  {7, 0x0107},
4103  {8, 0x005f},
4104  {8, 0x001f},
4105  {9, 0x009f},
4106  {7, 0x0117},
4107  {8, 0x007f},
4108  {8, 0x003f},
4109  {9, 0x00df},
4110  {7, 0x010f},
4111  {8, 0x006f},
4112  {8, 0x002f},
4113  {9, 0x00bf},
4114  {8, 0x000f},
4115  {8, 0x008f},
4116  {8, 0x004f},
4117  {9, 0x00ff}
4118};
4119
4120FlateHuffmanTab FlateStream::fixedLitCodeTab = {
4121  flateFixedLitCodeTabCodes, 9
4122};
4123
4124static FlateCode flateFixedDistCodeTabCodes[32] = {
4125  {5, 0x0000},
4126  {5, 0x0010},
4127  {5, 0x0008},
4128  {5, 0x0018},
4129  {5, 0x0004},
4130  {5, 0x0014},
4131  {5, 0x000c},
4132  {5, 0x001c},
4133  {5, 0x0002},
4134  {5, 0x0012},
4135  {5, 0x000a},
4136  {5, 0x001a},
4137  {5, 0x0006},
4138  {5, 0x0016},
4139  {5, 0x000e},
4140  {0, 0x0000},
4141  {5, 0x0001},
4142  {5, 0x0011},
4143  {5, 0x0009},
4144  {5, 0x0019},
4145  {5, 0x0005},
4146  {5, 0x0015},
4147  {5, 0x000d},
4148  {5, 0x001d},
4149  {5, 0x0003},
4150  {5, 0x0013},
4151  {5, 0x000b},
4152  {5, 0x001b},
4153  {5, 0x0007},
4154  {5, 0x0017},
4155  {5, 0x000f},
4156  {0, 0x0000}
4157};
4158
4159FlateHuffmanTab FlateStream::fixedDistCodeTab = {
4160  flateFixedDistCodeTabCodes, 5
4161};
4162
4163FlateStream::FlateStream(Stream *strA, int predictor, int columns,
4164                         int colors, int bits):
4165    FilterStream(strA) {
4166  if (predictor != 1) {
4167    pred = new StreamPredictor(this, predictor, columns, colors, bits);
4168    if (!pred->isOk()) {
4169      delete pred;
4170      pred = NULL;
4171    }
4172  } else {
4173    pred = NULL;
4174  }
4175  litCodeTab.codes = NULL;
4176  distCodeTab.codes = NULL;
4177  memset(buf, 0, flateWindow);
4178}
4179
4180FlateStream::~FlateStream() {
4181  if (litCodeTab.codes != fixedLitCodeTab.codes) {
4182    gfree(litCodeTab.codes);
4183  }
4184  if (distCodeTab.codes != fixedDistCodeTab.codes) {
4185    gfree(distCodeTab.codes);
4186  }
4187  if (pred) {
4188    delete pred;
4189  }
4190  delete str;
4191}
4192
4193void FlateStream::unfilteredReset() {
4194  index = 0;
4195  remain = 0;
4196  codeBuf = 0;
4197  codeSize = 0;
4198  compressedBlock = gFalse;
4199  endOfBlock = gTrue;
4200  eof = gTrue;
4201
4202  str->reset();
4203}
4204
4205void FlateStream::reset() {
4206  int cmf, flg;
4207
4208  unfilteredReset();
4209
4210  // read header
4211  //~ need to look at window size?
4212  endOfBlock = eof = gTrue;
4213  cmf = str->getChar();
4214  flg = str->getChar();
4215  if (cmf == EOF || flg == EOF)
4216    return;
4217  if ((cmf & 0x0f) != 0x08) {
4218    error(getPos(), "Unknown compression method in flate stream");
4219    return;
4220  }
4221  if ((((cmf << 8) + flg) % 31) != 0) {
4222    error(getPos(), "Bad FCHECK in flate stream");
4223    return;
4224  }
4225  if (flg & 0x20) {
4226    error(getPos(), "FDICT bit set in flate stream");
4227    return;
4228  }
4229
4230  eof = gFalse;
4231}
4232
4233int FlateStream::getChar() {
4234  int c;
4235
4236  if (pred) {
4237    return pred->getChar();
4238  }
4239  while (remain == 0) {
4240    if (endOfBlock && eof)
4241      return EOF;
4242    readSome();
4243  }
4244  c = buf[index];
4245  index = (index + 1) & flateMask;
4246  --remain;
4247  return c;
4248}
4249
4250int FlateStream::lookChar() {
4251  int c;
4252
4253  if (pred) {
4254    return pred->lookChar();
4255  }
4256  while (remain == 0) {
4257    if (endOfBlock && eof)
4258      return EOF;
4259    readSome();
4260  }
4261  c = buf[index];
4262  return c;
4263}
4264
4265int FlateStream::getRawChar() {
4266  int c;
4267
4268  while (remain == 0) {
4269    if (endOfBlock && eof)
4270      return EOF;
4271    readSome();
4272  }
4273  c = buf[index];
4274  index = (index + 1) & flateMask;
4275  --remain;
4276  return c;
4277}
4278
4279GooString *FlateStream::getPSFilter(int psLevel, char *indent) {
4280  GooString *s;
4281
4282  if (psLevel < 3 || pred) {
4283    return NULL;
4284  }
4285  if (!(s = str->getPSFilter(psLevel, indent))) {
4286    return NULL;
4287  }
4288  s->append(indent)->append("<< >> /FlateDecode filter\n");
4289  return s;
4290}
4291
4292GBool FlateStream::isBinary(GBool last) {
4293  return str->isBinary(gTrue);
4294}
4295
4296void FlateStream::readSome() {
4297  int code1, code2;
4298  int len, dist;
4299  int i, j, k;
4300  int c;
4301
4302  if (endOfBlock) {
4303    if (!startBlock())
4304      return;
4305  }
4306
4307  if (compressedBlock) {
4308    if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
4309      goto err;
4310    if (code1 < 256) {
4311      buf[index] = code1;
4312      remain = 1;
4313    } else if (code1 == 256) {
4314      endOfBlock = gTrue;
4315      remain = 0;
4316    } else {
4317      code1 -= 257;
4318      code2 = lengthDecode[code1].bits;
4319      if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
4320        goto err;
4321      len = lengthDecode[code1].first + code2;
4322      if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
4323        goto err;
4324      code2 = distDecode[code1].bits;
4325      if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
4326        goto err;
4327      dist = distDecode[code1].first + code2;
4328      i = index;
4329      j = (index - dist) & flateMask;
4330      for (k = 0; k < len; ++k) {
4331        buf[i] = buf[j];
4332        i = (i + 1) & flateMask;
4333        j = (j + 1) & flateMask;
4334      }
4335      remain = len;
4336    }
4337
4338  } else {
4339    len = (blockLen < flateWindow) ? blockLen : flateWindow;
4340    for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
4341      if ((c = str->getChar()) == EOF) {
4342        endOfBlock = eof = gTrue;
4343        break;
4344      }
4345      buf[j] = c & 0xff;
4346    }
4347    remain = i;
4348    blockLen -= len;
4349    if (blockLen == 0)
4350      endOfBlock = gTrue;
4351  }
4352
4353  return;
4354
4355err:
4356  error(getPos(), "Unexpected end of file in flate stream");
4357  endOfBlock = eof = gTrue;
4358  remain = 0;
4359}
4360
4361GBool FlateStream::startBlock() {
4362  int blockHdr;
4363  int c;
4364  int check;
4365
4366  // free the code tables from the previous block
4367  if (litCodeTab.codes != fixedLitCodeTab.codes) {
4368    gfree(litCodeTab.codes);
4369  }
4370  litCodeTab.codes = NULL;
4371  if (distCodeTab.codes != fixedDistCodeTab.codes) {
4372    gfree(distCodeTab.codes);
4373  }
4374  distCodeTab.codes = NULL;
4375
4376  // read block header
4377  blockHdr = getCodeWord(3);
4378  if (blockHdr & 1)
4379    eof = gTrue;
4380  blockHdr >>= 1;
4381
4382  // uncompressed block
4383  if (blockHdr == 0) {
4384    compressedBlock = gFalse;
4385    if ((c = str->getChar()) == EOF)
4386      goto err;
4387    blockLen = c & 0xff;
4388    if ((c = str->getChar()) == EOF)
4389      goto err;
4390    blockLen |= (c & 0xff) << 8;
4391    if ((c = str->getChar()) == EOF)
4392      goto err;
4393    check = c & 0xff;
4394    if ((c = str->getChar()) == EOF)
4395      goto err;
4396    check |= (c & 0xff) << 8;
4397    if (check != (~blockLen & 0xffff))
4398      error(getPos(), "Bad uncompressed block length in flate stream");
4399    codeBuf = 0;
4400    codeSize = 0;
4401
4402  // compressed block with fixed codes
4403  } else if (blockHdr == 1) {
4404    compressedBlock = gTrue;
4405    loadFixedCodes();
4406
4407  // compressed block with dynamic codes
4408  } else if (blockHdr == 2) {
4409    compressedBlock = gTrue;
4410    if (!readDynamicCodes()) {
4411      goto err;
4412    }
4413
4414  // unknown block type
4415  } else {
4416    goto err;
4417  }
4418
4419  endOfBlock = gFalse;
4420  return gTrue;
4421
4422err:
4423  error(getPos(), "Bad block header in flate stream");
4424  endOfBlock = eof = gTrue;
4425  return gFalse;
4426}
4427
4428void FlateStream::loadFixedCodes() {
4429  litCodeTab.codes = fixedLitCodeTab.codes;
4430  litCodeTab.maxLen = fixedLitCodeTab.maxLen;
4431  distCodeTab.codes = fixedDistCodeTab.codes;
4432  distCodeTab.maxLen = fixedDistCodeTab.maxLen;
4433}
4434
4435GBool FlateStream::readDynamicCodes() {
4436  int numCodeLenCodes;
4437  int numLitCodes;
4438  int numDistCodes;
4439  int codeLenCodeLengths[flateMaxCodeLenCodes];
4440  FlateHuffmanTab codeLenCodeTab;
4441  int len, repeat, code;
4442  int i;
4443
4444  codeLenCodeTab.codes = NULL;
4445
4446  // read lengths
4447  if ((numLitCodes = getCodeWord(5)) == EOF) {
4448    goto err;
4449  }
4450  numLitCodes += 257;
4451  if ((numDistCodes = getCodeWord(5)) == EOF) {
4452    goto err;
4453  }
4454  numDistCodes += 1;
4455  if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
4456    goto err;
4457  }
4458  numCodeLenCodes += 4;
4459  if (numLitCodes > flateMaxLitCodes ||
4460      numDistCodes > flateMaxDistCodes ||
4461      numCodeLenCodes > flateMaxCodeLenCodes) {
4462    goto err;
4463  }
4464
4465  // build the code length code table
4466  for (i = 0; i < flateMaxCodeLenCodes; ++i) {
4467    codeLenCodeLengths[i] = 0;
4468  }
4469  for (i = 0; i < numCodeLenCodes; ++i) {
4470    if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
4471      goto err;
4472    }
4473  }
4474  compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
4475
4476  // build the literal and distance code tables
4477  len = 0;
4478  repeat = 0;
4479  i = 0;
4480  while (i < numLitCodes + numDistCodes) {
4481    if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
4482      goto err;
4483    }
4484    if (code == 16) {
4485      if ((repeat = getCodeWord(2)) == EOF) {
4486        goto err;
4487      }
4488      repeat += 3;
4489      if (i + repeat > numLitCodes + numDistCodes) {
4490        goto err;
4491      }
4492      for (; repeat > 0; --repeat) {
4493        codeLengths[i++] = len;
4494      }
4495    } else if (code == 17) {
4496      if ((repeat = getCodeWord(3)) == EOF) {
4497        goto err;
4498      }
4499      repeat += 3;
4500      if (i + repeat > numLitCodes + numDistCodes) {
4501        goto err;
4502      }
4503      len = 0;
4504      for (; repeat > 0; --repeat) {
4505        codeLengths[i++] = 0;
4506      }
4507    } else if (code == 18) {
4508      if ((repeat = getCodeWord(7)) == EOF) {
4509        goto err;
4510      }
4511      repeat += 11;
4512      if (i + repeat > numLitCodes + numDistCodes) {
4513        goto err;
4514      }
4515      len = 0;
4516      for (; repeat > 0; --repeat) {
4517        codeLengths[i++] = 0;
4518      }
4519    } else {
4520      codeLengths[i++] = len = code;
4521    }
4522  }
4523  compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
4524  compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
4525
4526  gfree(codeLenCodeTab.codes);
4527  return gTrue;
4528
4529err:
4530  error(getPos(), "Bad dynamic code table in flate stream");
4531  gfree(codeLenCodeTab.codes);
4532  return gFalse;
4533}
4534
4535// Convert an array <lengths> of <n> lengths, in value order, into a
4536// Huffman code lookup table.
4537void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
4538  int tabSize, len, code, code2, skip, val, i, t;
4539
4540  // find max code length
4541  tab->maxLen = 0;
4542  for (val = 0; val < n; ++val) {
4543    if (lengths[val] > tab->maxLen) {
4544      tab->maxLen = lengths[val];
4545    }
4546  }
4547
4548  // allocate the table
4549  tabSize = 1 << tab->maxLen;
4550  tab->codes = (FlateCode *)gmallocn(tabSize, sizeof(FlateCode));
4551
4552  // clear the table
4553  for (i = 0; i < tabSize; ++i) {
4554    tab->codes[i].len = 0;
4555    tab->codes[i].val = 0;
4556  }
4557
4558  // build the table
4559  for (len = 1, code = 0, skip = 2;
4560       len <= tab->maxLen;
4561       ++len, code <<= 1, skip <<= 1) {
4562    for (val = 0; val < n; ++val) {
4563      if (lengths[val] == len) {
4564
4565        // bit-reverse the code
4566        code2 = 0;
4567        t = code;
4568        for (i = 0; i < len; ++i) {
4569          code2 = (code2 << 1) | (t & 1);
4570          t >>= 1;
4571        }
4572
4573        // fill in the table entries
4574        for (i = code2; i < tabSize; i += skip) {
4575          tab->codes[i].len = (Gushort)len;
4576          tab->codes[i].val = (Gushort)val;
4577        }
4578
4579        ++code;
4580      }
4581    }
4582  }
4583}
4584
4585int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
4586  FlateCode *code;
4587  int c;
4588
4589  while (codeSize < tab->maxLen) {
4590    if ((c = str->getChar()) == EOF) {
4591      break;
4592    }
4593    codeBuf |= (c & 0xff) << codeSize;
4594    codeSize += 8;
4595  }
4596  code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
4597  if (codeSize == 0 || codeSize < code->len || code->len == 0) {
4598    return EOF;
4599  }
4600  codeBuf >>= code->len;
4601  codeSize -= code->len;
4602  return (int)code->val;
4603}
4604
4605int FlateStream::getCodeWord(int bits) {
4606  int c;
4607
4608  while (codeSize < bits) {
4609    if ((c = str->getChar()) == EOF)
4610      return EOF;
4611    codeBuf |= (c & 0xff) << codeSize;
4612    codeSize += 8;
4613  }
4614  c = codeBuf & ((1 << bits) - 1);
4615  codeBuf >>= bits;
4616  codeSize -= bits;
4617  return c;
4618}
4619#endif
4620
4621//------------------------------------------------------------------------
4622// EOFStream
4623//------------------------------------------------------------------------
4624
4625EOFStream::EOFStream(Stream *strA):
4626    FilterStream(strA) {
4627}
4628
4629EOFStream::~EOFStream() {
4630  delete str;
4631}
4632
4633//------------------------------------------------------------------------
4634// FixedLengthEncoder
4635//------------------------------------------------------------------------
4636
4637FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
4638    FilterStream(strA) {
4639  length = lengthA;
4640  count = 0;
4641}
4642
4643FixedLengthEncoder::~FixedLengthEncoder() {
4644  if (str->isEncoder())
4645    delete str;
4646}
4647
4648void FixedLengthEncoder::reset() {
4649  str->reset();
4650  count = 0;
4651}
4652
4653int FixedLengthEncoder::getChar() {
4654  if (length >= 0 && count >= length)
4655    return EOF;
4656  ++count;
4657  return str->getChar();
4658}
4659
4660int FixedLengthEncoder::lookChar() {
4661  if (length >= 0 && count >= length)
4662    return EOF;
4663  return str->getChar();
4664}
4665
4666GBool FixedLengthEncoder::isBinary(GBool last) {
4667  return str->isBinary(gTrue);
4668}
4669
4670//------------------------------------------------------------------------
4671// ASCIIHexEncoder
4672//------------------------------------------------------------------------
4673
4674ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
4675    FilterStream(strA) {
4676  bufPtr = bufEnd = buf;
4677  lineLen = 0;
4678  eof = gFalse;
4679}
4680
4681ASCIIHexEncoder::~ASCIIHexEncoder() {
4682  if (str->isEncoder()) {
4683    delete str;
4684  }
4685}
4686
4687void ASCIIHexEncoder::reset() {
4688  str->reset();
4689  bufPtr = bufEnd = buf;
4690  lineLen = 0;
4691  eof = gFalse;
4692}
4693
4694GBool ASCIIHexEncoder::fillBuf() {
4695  static const char *hex = "0123456789abcdef";
4696  int c;
4697
4698  if (eof) {
4699    return gFalse;
4700  }
4701  bufPtr = bufEnd = buf;
4702  if ((c = str->getChar()) == EOF) {
4703    *bufEnd++ = '>';
4704    eof = gTrue;
4705  } else {
4706    if (lineLen >= 64) {
4707      *bufEnd++ = '\n';
4708      lineLen = 0;
4709    }
4710    *bufEnd++ = hex[(c >> 4) & 0x0f];
4711    *bufEnd++ = hex[c & 0x0f];
4712    lineLen += 2;
4713  }
4714  return gTrue;
4715}
4716
4717//------------------------------------------------------------------------
4718// ASCII85Encoder
4719//------------------------------------------------------------------------
4720
4721ASCII85Encoder::ASCII85Encoder(Stream *strA):
4722    FilterStream(strA) {
4723  bufPtr = bufEnd = buf;
4724  lineLen = 0;
4725  eof = gFalse;
4726}
4727
4728ASCII85Encoder::~ASCII85Encoder() {
4729  if (str->isEncoder())
4730    delete str;
4731}
4732
4733void ASCII85Encoder::reset() {
4734  str->reset();
4735  bufPtr = bufEnd = buf;
4736  lineLen = 0;
4737  eof = gFalse;
4738}
4739
4740GBool ASCII85Encoder::fillBuf() {
4741  Guint t;
4742  char buf1[5];
4743  int c0, c1, c2, c3;
4744  int n, i;
4745
4746  if (eof) {
4747    return gFalse;
4748  }
4749  c0 = str->getChar();
4750  c1 = str->getChar();
4751  c2 = str->getChar();
4752  c3 = str->getChar();
4753  bufPtr = bufEnd = buf;
4754  if (c3 == EOF) {
4755    if (c0 == EOF) {
4756      n = 0;
4757      t = 0;
4758    } else {
4759      if (c1 == EOF) {
4760        n = 1;
4761        t = c0 << 24;
4762      } else if (c2 == EOF) {
4763        n = 2;
4764        t = (c0 << 24) | (c1 << 16);
4765      } else {
4766        n = 3;
4767        t = (c0 << 24) | (c1 << 16) | (c2 << 8);
4768      }
4769      for (i = 4; i >= 0; --i) {
4770        buf1[i] = (char)(t % 85 + 0x21);
4771        t /= 85;
4772      }
4773      for (i = 0; i <= n; ++i) {
4774        *bufEnd++ = buf1[i];
4775        if (++lineLen == 65) {
4776          *bufEnd++ = '\n';
4777          lineLen = 0;
4778        }
4779      }
4780    }
4781    *bufEnd++ = '~';
4782    *bufEnd++ = '>';
4783    eof = gTrue;
4784  } else {
4785    t = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3;
4786    if (t == 0) {
4787      *bufEnd++ = 'z';
4788      if (++lineLen == 65) {
4789        *bufEnd++ = '\n';
4790        lineLen = 0;
4791      }
4792    } else {
4793      for (i = 4; i >= 0; --i) {
4794        buf1[i] = (char)(t % 85 + 0x21);
4795        t /= 85;
4796      }
4797      for (i = 0; i <= 4; ++i) {
4798        *bufEnd++ = buf1[i];
4799        if (++lineLen == 65) {
4800          *bufEnd++ = '\n';
4801          lineLen = 0;
4802        }
4803      }
4804    }
4805  }
4806  return gTrue;
4807}
4808
4809//------------------------------------------------------------------------
4810// RunLengthEncoder
4811//------------------------------------------------------------------------
4812
4813RunLengthEncoder::RunLengthEncoder(Stream *strA):
4814    FilterStream(strA) {
4815  bufPtr = bufEnd = nextEnd = buf;
4816  eof = gFalse;
4817}
4818
4819RunLengthEncoder::~RunLengthEncoder() {
4820  if (str->isEncoder())
4821    delete str;
4822}
4823
4824void RunLengthEncoder::reset() {
4825  str->reset();
4826  bufPtr = bufEnd = nextEnd = buf;
4827  eof = gFalse;
4828}
4829
4830//
4831// When fillBuf finishes, buf[] looks like this:
4832//   +-----+--------------+-----------------+--
4833//   + tag | ... data ... | next 0, 1, or 2 |
4834//   +-----+--------------+-----------------+--
4835//    ^                    ^                 ^
4836//    bufPtr               bufEnd            nextEnd
4837//
4838GBool RunLengthEncoder::fillBuf() {
4839  int c, c1, c2;
4840  int n;
4841
4842  // already hit EOF?
4843  if (eof)
4844    return gFalse;
4845
4846  // grab two bytes
4847  if (nextEnd < bufEnd + 1) {
4848    if ((c1 = str->getChar()) == EOF) {
4849      eof = gTrue;
4850      return gFalse;
4851    }
4852  } else {
4853    c1 = bufEnd[0] & 0xff;
4854  }
4855  if (nextEnd < bufEnd + 2) {
4856    if ((c2 = str->getChar()) == EOF) {
4857      eof = gTrue;
4858      buf[0] = 0;
4859      buf[1] = c1;
4860      bufPtr = buf;
4861      bufEnd = &buf[2];
4862      return gTrue;
4863    }
4864  } else {
4865    c2 = bufEnd[1] & 0xff;
4866  }
4867
4868  // check for repeat
4869  c = 0; // make gcc happy
4870  if (c1 == c2) {
4871    n = 2;
4872    while (n < 128 && (c = str->getChar()) == c1)
4873      ++n;
4874    buf[0] = (char)(257 - n);
4875    buf[1] = c1;
4876    bufEnd = &buf[2];
4877    if (c == EOF) {
4878      eof = gTrue;
4879    } else if (n < 128) {
4880      buf[2] = c;
4881      nextEnd = &buf[3];
4882    } else {
4883      nextEnd = bufEnd;
4884    }
4885
4886  // get up to 128 chars
4887  } else {
4888    buf[1] = c1;
4889    buf[2] = c2;
4890    n = 2;
4891    while (n < 128) {
4892      if ((c = str->getChar()) == EOF) {
4893        eof = gTrue;
4894        break;
4895      }
4896      ++n;
4897      buf[n] = c;
4898      if (buf[n] == buf[n-1])
4899        break;
4900    }
4901    if (buf[n] == buf[n-1]) {
4902      buf[0] = (char)(n-2-1);
4903      bufEnd = &buf[n-1];
4904      nextEnd = &buf[n+1];
4905    } else {
4906      buf[0] = (char)(n-1);
4907      bufEnd = nextEnd = &buf[n+1];
4908    }
4909  }
4910  bufPtr = buf;
4911  return gTrue;
4912}
Note: See TracBrowser for help on using the repository browser.