]> www.fi.muni.cz Git - evince.git/blobdiff - pdf/xpdf/Stream.cc
Imported Xpdf 2.03 and fixed build.
[evince.git] / pdf / xpdf / Stream.cc
index 11b51b60fe8626a0c0020a19ed74897c7e94cae1..e770b61dec2953ae1f442e26b9125102ef2dd4d7 100644 (file)
@@ -84,7 +84,7 @@ char *Stream::getLine(char *buf, int size) {
   return buf;
 }
 
-GString *Stream::getPSFilter(char *indent) {
+GString *Stream::getPSFilter(int psLevel, char *indent) {
   return new GString();
 }
 
@@ -696,13 +696,14 @@ void FileStream::moveStart(int delta) {
 // MemStream
 //------------------------------------------------------------------------
 
-MemStream::MemStream(char *bufA, Guint lengthA, Object *dictA):
+MemStream::MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA):
     BaseStream(dictA) {
   buf = bufA;
-  needFree = gFalse;
+  start = startA;
   length = lengthA;
-  bufEnd = buf + length;
-  bufPtr = buf;
+  bufEnd = buf + start + length;
+  bufPtr = buf + start;
+  needFree = gFalse;
 }
 
 MemStream::~MemStream() {
@@ -711,20 +712,22 @@ MemStream::~MemStream() {
   }
 }
 
-Stream *MemStream::makeSubStream(Guint start, GBool limited,
+Stream *MemStream::makeSubStream(Guint startA, GBool limited,
                                 Guint lengthA, Object *dictA) {
+  MemStream *subStr;
   Guint newLength;
 
-  if (!limited || start + lengthA > length) {
-    newLength = length - start;
+  if (!limited || startA + lengthA > start + length) {
+    newLength = start + length - startA;
   } else {
     newLength = lengthA;
   }
-  return new MemStream(buf + start, newLength, dictA);
+  subStr = new MemStream(buf, startA, newLength, dictA);
+  return subStr;
 }
 
 void MemStream::reset() {
-  bufPtr = buf;
+  bufPtr = buf + start;
 #ifndef NO_DECRYPTION
   if (decrypt) {
     decrypt->reset();
@@ -736,24 +739,24 @@ void MemStream::close() {
 }
 
 void MemStream::setPos(Guint pos, int dir) {
+  Guint i;
+
   if (dir >= 0) {
-    if (pos > length) {
-      bufPtr = bufEnd;
-    } else {
-      bufPtr = buf + pos;
-    }
+    i = pos;
   } else {
-    if (pos > length) {
-      bufPtr = buf;
-    } else {
-      bufPtr = bufEnd - pos;
-    }
+    i = start + length - pos;
   }
+  if (i < start) {
+    i = start;
+  } else if (i > start + length) {
+    i = start + length;
+  }
+  bufPtr = buf + i;
 }
 
 void MemStream::moveStart(int delta) {
-  buf += delta;
-  bufPtr = buf;
+  start += delta;
+  bufPtr = buf + start;
 }
 
 #ifndef NO_DECRYPTION
@@ -764,12 +767,13 @@ void MemStream::doDecryption(Guchar *fileKey, int keyLength,
 
   this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
   if (decrypt) {
-    newBuf = (char *)gmalloc(bufEnd - buf);
-    for (p = buf, q = newBuf; p < bufEnd; ++p, ++q) {
+    newBuf = (char *)gmalloc(length);
+    for (p = buf + start, q = newBuf; p < bufEnd; ++p, ++q) {
       *q = (char)decrypt->decryptByte((Guchar)*p);
     }
-    bufEnd = newBuf + (bufEnd - buf);
-    bufPtr = newBuf + (bufPtr - buf);
+    bufEnd = newBuf + length;
+    bufPtr = newBuf + (bufPtr - (buf + start));
+    start = 0;
     buf = newBuf;
     needFree = gTrue;
   }
@@ -880,10 +884,13 @@ int ASCIIHexStream::lookChar() {
   return buf;
 }
 
-GString *ASCIIHexStream::getPSFilter(char *indent) {
+GString *ASCIIHexStream::getPSFilter(int psLevel, char *indent) {
   GString *s;
 
-  if (!(s = str->getPSFilter(indent))) {
+  if (psLevel < 2) {
+    return NULL;
+  }
+  if (!(s = str->getPSFilter(psLevel, indent))) {
     return NULL;
   }
   s->append(indent)->append("/ASCIIHexDecode filter\n");
@@ -958,10 +965,13 @@ int ASCII85Stream::lookChar() {
   return b[index];
 }
 
-GString *ASCII85Stream::getPSFilter(char *indent) {
+GString *ASCII85Stream::getPSFilter(int psLevel, char *indent) {
   GString *s;
 
-  if (!(s = str->getPSFilter(indent))) {
+  if (psLevel < 2) {
+    return NULL;
+  }
+  if (!(s = str->getPSFilter(psLevel, indent))) {
     return NULL;
   }
   s->append(indent)->append("/ASCII85Decode filter\n");
@@ -1137,13 +1147,13 @@ int LZWStream::getCode() {
   return code;
 }
 
-GString *LZWStream::getPSFilter(char *indent) {
+GString *LZWStream::getPSFilter(int psLevel, char *indent) {
   GString *s;
 
-  if (pred) {
+  if (psLevel < 2 || pred) {
     return NULL;
   }
-  if (!(s = str->getPSFilter(indent))) {
+  if (!(s = str->getPSFilter(psLevel, indent))) {
     return NULL;
   }
   s->append(indent)->append("/LZWDecode filter\n");
@@ -1174,10 +1184,13 @@ void RunLengthStream::reset() {
   eof = gFalse;
 }
 
-GString *RunLengthStream::getPSFilter(char *indent) {
+GString *RunLengthStream::getPSFilter(int psLevel, char *indent) {
   GString *s;
 
-  if (!(s = str->getPSFilter(indent))) {
+  if (psLevel < 2) {
+    return NULL;
+  }
+  if (!(s = str->getPSFilter(psLevel, indent))) {
     return NULL;
   }
   s->append(indent)->append("/RunLengthDecode filter\n");
@@ -1334,12 +1347,14 @@ int CCITTFaxStream::lookChar() {
              code2 += code3 = getWhiteCode();
            } while (code3 >= 64);
          }
-         codingLine[a0 + 1] = a0New + code1;
-         ++a0;
-         a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
-         ++a0;
-         while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
-           b1 += 2;
+         if (code1 > 0 || code2 > 0) {
+           codingLine[a0 + 1] = a0New + code1;
+           ++a0;
+           a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
+           ++a0;
+           while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+             b1 += 2;
+         }
          break;
        case twoDimVert0:
          a0New = codingLine[++a0] = refLine[b1];
@@ -1504,7 +1519,7 @@ int CCITTFaxStream::lookChar() {
          return EOF;
        }
        eatBits(1);
-       code1 = look13Bits();
+       code1 = lookBits(13);
       } while ((code1 >> 1) != 0x001);
       eatBits(12); 
       codingLine[++a0] = columns;
@@ -1724,11 +1739,14 @@ short CCITTFaxStream::lookBits(int n) {
   return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
 }
 
-GString *CCITTFaxStream::getPSFilter(char *indent) {
+GString *CCITTFaxStream::getPSFilter(int psLevel, char *indent) {
   GString *s;
   char s1[50];
 
-  if (!(s = str->getPSFilter(indent))) {
+  if (psLevel < 2) {
+    return NULL;
+  }
+  if (!(s = str->getPSFilter(psLevel, indent))) {
     return NULL;
   }
   s->append(indent)->append("<< ");
@@ -1864,6 +1882,7 @@ void DCTStream::reset() {
   numDCHuffTables = 0;
   numACHuffTables = 0;
   colorXform = 0;
+  gotJFIFMarker = gFalse;
   gotAdobeMarker = gFalse;
   restartInterval = 0;
 
@@ -1894,7 +1913,12 @@ void DCTStream::reset() {
 
   // figure out color transform
   if (!gotAdobeMarker && numComps == 3) {
-    if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
+    if (gotJFIFMarker) {
+      colorXform = 1;
+    } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
+              compInfo[2].id == 66) { // ASCII "RGB"
+      colorXform = 0;
+    } else {
       colorXform = 1;
     }
   }
@@ -2142,7 +2166,7 @@ GBool DCTStream::readMCURow() {
 void DCTStream::readScan() {
   int data[64];
   int x1, y1, dx1, dy1, x2, y2, y3, cc, i;
-  int h, v, horiz, vert, hSub, vSub;
+  int h, v, horiz, vert, vSub;
   int *p1;
   int c;
 
@@ -2185,7 +2209,6 @@ void DCTStream::readScan() {
        v = compInfo[cc].vSample;
        horiz = mcuWidth / h;
        vert = mcuHeight / v;
-       hSub = horiz / 8;
        vSub = vert / 8;
        for (y2 = 0; y2 < dy1; y2 += vert) {
          for (x2 = 0; x2 < dx1; x2 += horiz) {
@@ -2810,7 +2833,6 @@ GBool DCTStream::readHeader() {
       break;
     case 0xd9:                 // EOI
       return gFalse;
-      break;
     case 0xda:                 // SOS
       if (!readScanInfo()) {
        return gFalse;
@@ -2827,6 +2849,11 @@ GBool DCTStream::readHeader() {
        return gFalse;
       }
       break;
+    case 0xe0:                 // APP0
+      if (!readJFIFMarker()) {
+       return gFalse;
+      }
+      break;
     case 0xee:                 // APP14
       if (!readAdobeMarker()) {
        return gFalse;
@@ -2923,14 +2950,21 @@ GBool DCTStream::readScanInfo() {
   }
   for (i = 0; i < scanInfo.numComps; ++i) {
     id = str->getChar();
-    for (j = 0; j < numComps; ++j) {
-      if (id == compInfo[j].id) {
-       break;
+    // some (broken) DCT streams reuse ID numbers, but at least they
+    // keep the components in order, so we check compInfo[i] first to
+    // work around the problem
+    if (id == compInfo[i].id) {
+      j = i;
+    } else {
+      for (j = 0; j < numComps; ++j) {
+       if (id == compInfo[j].id) {
+         break;
+       }
+      }
+      if (j == numComps) {
+       error(getPos(), "Bad DCT component ID in scan info block");
+       return gFalse;
       }
-    }
-    if (j == numComps) {
-      error(getPos(), "Bad DCT component ID in scan info block");
-      return gFalse;
     }
     scanInfo.comp[j] = gTrue;
     c = str->getChar();
@@ -3023,6 +3057,36 @@ GBool DCTStream::readRestartInterval() {
   return gTrue;
 }
 
+GBool DCTStream::readJFIFMarker() {
+  int length, i;
+  char buf[5];
+  int c;
+
+  length = read16();
+  length -= 2;
+  if (length >= 5) {
+    for (i = 0; i < 5; ++i) {
+      if ((c = str->getChar()) == EOF) {
+       error(getPos(), "Bad DCT APP0 marker");
+       return gFalse;
+      }
+      buf[i] = c;
+    }
+    length -= 5;
+    if (!memcmp(buf, "JFIF\0", 5)) {
+      gotJFIFMarker = gTrue;
+    }
+  }
+  while (length > 0) {
+    if (str->getChar() == EOF) {
+      error(getPos(), "Bad DCT APP0 marker");
+      return gFalse;
+    }
+    --length;
+  }
+  return gTrue;
+}
+
 GBool DCTStream::readAdobeMarker() {
   int length, i;
   char buf[12];
@@ -3090,10 +3154,13 @@ int DCTStream::read16() {
   return (c1 << 8) + c2;
 }
 
-GString *DCTStream::getPSFilter(char *indent) {
+GString *DCTStream::getPSFilter(int psLevel, char *indent) {
   GString *s;
 
-  if (!(s = str->getPSFilter(indent))) {
+  if (psLevel < 2) {
+    return NULL;
+  }
+  if (!(s = str->getPSFilter(psLevel, indent))) {
     return NULL;
   }
   s->append(indent)->append("<< >> /DCTDecode filter\n");
@@ -3280,8 +3347,17 @@ int FlateStream::getRawChar() {
   return c;
 }
 
-GString *FlateStream::getPSFilter(char *indent) {
-  return NULL;
+GString *FlateStream::getPSFilter(int psLevel, char *indent) {
+  GString *s;
+
+  if (psLevel < 3 || pred) {
+    return NULL;
+  }
+  if (!(s = str->getPSFilter(psLevel, indent))) {
+    return NULL;
+  }
+  s->append(indent)->append("<< >> /FlateDecode filter\n");
+  return s;
 }
 
 GBool FlateStream::isBinary(GBool last) {
@@ -3658,9 +3734,6 @@ void FixedLengthEncoder::reset() {
   count = 0;
 }
 
-void FixedLengthEncoder::close() {
-}
-
 int FixedLengthEncoder::getChar() {
   if (length >= 0 && count >= length)
     return EOF;
@@ -3698,9 +3771,6 @@ void ASCIIHexEncoder::reset() {
   eof = gFalse;
 }
 
-void ASCIIHexEncoder::close() {
-}
-
 GBool ASCIIHexEncoder::fillBuf() {
   static char *hex = "0123456789abcdef";
   int c;
@@ -3747,9 +3817,6 @@ void ASCII85Encoder::reset() {
   eof = gFalse;
 }
 
-void ASCII85Encoder::close() {
-}
-
 GBool ASCII85Encoder::fillBuf() {
   Gulong t;
   char buf1[5];
@@ -3817,9 +3884,6 @@ void RunLengthEncoder::reset() {
   eof = gFalse;
 }
 
-void RunLengthEncoder::close() {
-}
-
 //
 // When fillBuf finishes, buf[] looks like this:
 //   +-----+--------------+-----------------+--