[poppler] 2 commits - poppler/Catalog.cc poppler/DCTStream.cc poppler/DCTStream.h poppler/GfxFont.cc poppler/GfxState.cc poppler/JPEG2000Stream.cc poppler/JPEG2000Stream.h poppler/Link.cc poppler/Object.h poppler/Stream.cc poppler/Stream.h

Albert Astals Cid aacid at kemper.freedesktop.org
Mon Jun 21 11:25:06 PDT 2010


 poppler/Catalog.cc        |   12 ----
 poppler/DCTStream.cc      |   51 ++++++++++++++-----
 poppler/DCTStream.h       |    3 +
 poppler/GfxFont.cc        |   22 +-------
 poppler/GfxState.cc       |   36 ++++----------
 poppler/JPEG2000Stream.cc |   67 +++++++-------------------
 poppler/JPEG2000Stream.h  |   38 ++++++++++++++
 poppler/Link.cc           |   14 +----
 poppler/Object.h          |    4 +
 poppler/Stream.cc         |   90 +++++++++++++++++++----------------
 poppler/Stream.h          |  118 +++++++++++++++++++++++++++++++++++++++++++++-
 11 files changed, 282 insertions(+), 173 deletions(-)

New commits:
commit 58a53ca0a4e8434e8478f8fe121067dcf05c017d
Author: Albert Astals Cid <aacid at kde.org>
Date:   Mon Jun 21 19:24:20 2010 +0100

    sqrt is much faster than pow 0.5

diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index b7dd8c7..7140efc 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -965,9 +965,9 @@ void GfxCalRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
   r = xyzrgb[0][0] * X + xyzrgb[0][1] * Y + xyzrgb[0][2] * Z;
   g = xyzrgb[1][0] * X + xyzrgb[1][1] * Y + xyzrgb[1][2] * Z;
   b = xyzrgb[2][0] * X + xyzrgb[2][1] * Y + xyzrgb[2][2] * Z;
-  rgb->r = dblToCol(pow(clip01(r), 0.5));
-  rgb->g = dblToCol(pow(clip01(g), 0.5));
-  rgb->b = dblToCol(pow(clip01(b), 0.5));
+  rgb->r = dblToCol(sqrt(clip01(r)));
+  rgb->g = dblToCol(sqrt(clip01(g)));
+  rgb->b = dblToCol(sqrt(clip01(b)));
 }
 
 void GfxCalRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
commit bf86a9fc464aca57ebec207a213dcc2cc6031940
Author: Albert Astals Cid <aacid at kde.org>
Date:   Mon Jun 21 19:20:47 2010 +0100

    introduce getChars to save some method calls
    
    Can give us a decent speedup when we go a lot though this methods

diff --git a/poppler/Catalog.cc b/poppler/Catalog.cc
index 900cdd7..dbf9af2 100644
--- a/poppler/Catalog.cc
+++ b/poppler/Catalog.cc
@@ -192,7 +192,6 @@ GooString *Catalog::readMetadata() {
   GooString *s;
   Dict *dict;
   Object obj;
-  int c;
 
   if (metadata.isNone()) {
     Object catDict;
@@ -217,10 +216,7 @@ GooString *Catalog::readMetadata() {
   }
   obj.free();
   s = new GooString();
-  metadata.streamReset();
-  while ((c = metadata.streamGetChar()) != EOF) {
-    s->append(c);
-  }
+  metadata.getStream()->fillGooString(s);
   metadata.streamClose();
   return s;
 }
@@ -409,11 +405,7 @@ GooString *Catalog::getJS(int i)
   else if (obj2.isStream()) {
     Stream *stream = obj2.getStream();
     js = new GooString();
-    stream->reset();
-    int j;
-    while ((j = stream->getChar()) != EOF) {
-      js->append((char)j);
-    }
+    stream->fillGooString(js);
   }
   obj2.free();
   obj.free();
diff --git a/poppler/DCTStream.cc b/poppler/DCTStream.cc
index 5cbaced..1b15619 100644
--- a/poppler/DCTStream.cc
+++ b/poppler/DCTStream.cc
@@ -145,27 +145,48 @@ void DCTStream::reset() {
   }
 }
 
+// we can not go with inline since gcc
+// refuses to inline because of setjmp
+#define DO_GET_CHAR \
+  if (current == limit) { \
+    if (cinfo.output_scanline < cinfo.output_height) \
+    { \
+      if (!setjmp(src.setjmp_buffer)) \
+      { \
+        if (!jpeg_read_scanlines(&cinfo, row_buffer, 1)) c = EOF; \
+        else { \
+          current = &row_buffer[0][0]; \
+          limit = &row_buffer[0][(cinfo.output_width - 1) * cinfo.output_components] + cinfo.output_components; \
+          c = *current; \
+          ++current; \
+        } \
+      } \
+      else c = EOF; \
+    } \
+    else c = EOF; \
+  } else { \
+    c = *current; \
+    ++current; \
+  } \
+
 int DCTStream::getChar() {
   int c;
 
-  if (current == limit) {
-    if (cinfo.output_scanline < cinfo.output_height)
-    {
-      if (!setjmp(src.setjmp_buffer))
-      {
-        if (!jpeg_read_scanlines(&cinfo, row_buffer, 1)) return EOF;
-        current = &row_buffer[0][0];
-        limit = &row_buffer[0][(cinfo.output_width - 1) * cinfo.output_components] + cinfo.output_components;
-      }
-      else return EOF;
-    }
-    else return EOF;
-  }
-  c = *current;
-  ++current;
+  DO_GET_CHAR
+  
   return c;
 }
 
+int DCTStream::getChars(int nChars, Guchar *buffer) {
+  int c;
+  for (int i = 0; i < nChars; ++i) {
+    DO_GET_CHAR
+    if (likely(c != EOF)) buffer[i] = c;
+    else return i;
+  }
+  return nChars;
+}
+
 int DCTStream::lookChar() {
   return *current;
 }
diff --git a/poppler/DCTStream.h b/poppler/DCTStream.h
index 6768ff2..65196ec 100644
--- a/poppler/DCTStream.h
+++ b/poppler/DCTStream.h
@@ -69,6 +69,9 @@ public:
 private:
   void init();
 
+  virtual GBool hasGetChars() { return true; }
+  virtual int getChars(int nChars, Guchar *buffer);
+
   JSAMPLE *current;
   JSAMPLE *limit;
   struct jpeg_decompress_struct cinfo;
diff --git a/poppler/GfxFont.cc b/poppler/GfxFont.cc
index f823faf..aeab6f3 100644
--- a/poppler/GfxFont.cc
+++ b/poppler/GfxFont.cc
@@ -10,7 +10,7 @@
 //
 // Modified under the Poppler project - http://poppler.freedesktop.org
 //
-// Copyright (C) 2005, 2006, 2008, 2009 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2005, 2006, 2008-2010 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2005, 2006 Kristian Høgsberg <krh at redhat.com>
 // Copyright (C) 2006 Takashi Iwai <tiwai at suse.de>
 // Copyright (C) 2007 Julien Rebetez <julienr at svn.gnome.org>
@@ -421,17 +421,13 @@ CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits,
 					      CharCodeToUnicode *ctu) {
   GooString *buf;
   Object obj1;
-  int c;
 
   if (!fontDict->lookup("ToUnicode", &obj1)->isStream()) {
     obj1.free();
     return NULL;
   }
   buf = new GooString();
-  obj1.streamReset();
-  while ((c = obj1.streamGetChar()) != EOF) {
-    buf->append(c);
-  }
+  obj1.getStream()->fillGooString(buf);
   obj1.streamClose();
   obj1.free();
   if (ctu) {
@@ -488,8 +484,6 @@ char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
   char *buf;
   Object obj1, obj2;
   Stream *str;
-  int c;
-  int size, i;
 
   obj1.initRef(embFontID.num, embFontID.gen);
   obj1.fetch(xref, &obj2);
@@ -503,17 +497,7 @@ char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
   }
   str = obj2.getStream();
 
-  buf = NULL;
-  i = size = 0;
-  str->reset();
-  while ((c = str->getChar()) != EOF) {
-    if (i == size) {
-      size += 4096;
-      buf = (char *)grealloc(buf, size);
-    }
-    buf[i++] = c;
-  }
-  *len = i;
+  buf = (char*)str->toUnsignedChars(len);
   str->close();
 
   obj2.free();
diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index 61dac24..b7dd8c7 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -1484,22 +1484,11 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, Gfx *gfx) {
   arr->get(1, &obj1);
   dict = obj1.streamGetDict();
   Guchar *profBuf;
-  unsigned int bufSize;
   Stream *iccStream = obj1.getStream();
-  int c;
-  unsigned int size = 0;
-
-  bufSize = 65536;
-  profBuf = (Guchar *)gmallocn(bufSize,1);
-  iccStream->reset();
-  while ((c = iccStream->getChar()) != EOF) {
-    if (bufSize <= size) {
-      bufSize += 65536;
-      profBuf = (Guchar *)greallocn(profBuf,bufSize,1);
-    }
-    profBuf[size++] = c;
-  }
-  cmsHPROFILE hp = cmsOpenProfileFromMem(profBuf,size);
+  int length = 0;
+
+  profBuf = iccStream->toUnsignedChars(&length, 65536, 65536);
+  cmsHPROFILE hp = cmsOpenProfileFromMem(profBuf,length);
   gfree(profBuf);
   if (hp == 0) {
     error(-1, "read ICCBased color space profile error");
@@ -1718,7 +1707,6 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr, Gfx *gfx) {
   GfxColorSpace *baseA;
   int indexHighA;
   Object obj1;
-  int x;
   char *s;
   int n, i, j;
 
@@ -1755,12 +1743,10 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr, Gfx *gfx) {
   if (obj1.isStream()) {
     obj1.streamReset();
     for (i = 0; i <= indexHighA; ++i) {
-      for (j = 0; j < n; ++j) {
-	if ((x = obj1.streamGetChar()) == EOF) {
-	  error(-1, "Bad Indexed color space (lookup table stream too short) padding with zeroes");
-	  x = 0;
-	}
-	cs->lookup[i*n + j] = (Guchar)x;
+      const int readChars = obj1.streamGetChars(n, &cs->lookup[i*n]);
+      for (j = readChars; j < n; ++j) {
+        error(-1, "Bad Indexed color space (lookup table stream too short) padding with zeroes");
+        cs->lookup[i*n + j] = 0;
       }
     }
     obj1.streamClose();
diff --git a/poppler/JPEG2000Stream.cc b/poppler/JPEG2000Stream.cc
index 3b301f7..d52f088 100644
--- a/poppler/JPEG2000Stream.cc
+++ b/poppler/JPEG2000Stream.cc
@@ -4,7 +4,7 @@
 //
 // A JPX stream decoder using OpenJPEG
 //
-// Copyright 2008, 2009 Albert Astals Cid <aacid at kde.org>
+// Copyright 2008-2010 Albert Astals Cid <aacid at kde.org>
 //
 // Licensed under GPLv2 or later
 //
@@ -43,42 +43,34 @@ int JPXStream::getPos() {
   return counter;
 }
 
+int JPXStream::getChars(int nChars, Guchar *buffer) {
+  for (int i = 0; i < nChars; ++i) {
+    const int c = doGetChar();
+    if (likely(c != EOF)) buffer[i] = c;
+    else return i;
+  }
+  return nChars;
+}
+
 int JPXStream::getChar() {
-  int result = lookChar();
-  ++counter;
-  return result;
+  return doGetChar();
 }
 
-#define BUFFER_INCREASE 4096
+#define BUFFER_INITIAL_SIZE 4096
 
 void JPXStream::init()
 {
   Object oLen;
   if (getDict()) getDict()->lookup("Length", &oLen);
 
-  int bufSize = BUFFER_INCREASE;
+  int bufSize = BUFFER_INITIAL_SIZE;
   if (oLen.isInt()) bufSize = oLen.getInt();
   oLen.free();
 
-  unsigned char *buf = (unsigned char*)gmallocn(bufSize, sizeof(unsigned char));
-  int index = 0;
-
-  str->reset();
-  int c = str->getChar();
-  while(c != EOF)
-  {
-    if (index >= bufSize)
-    {
-      bufSize += BUFFER_INCREASE;
-      buf = (unsigned char*)greallocn(buf, bufSize, sizeof(unsigned char));
-    }
-    buf[index] = c;
-    ++index;
-    c = str->getChar();
-  }
-
-  init2(buf, index, CODEC_JP2);
-
+  
+  int length = 0;
+  unsigned char *buf = str->toUnsignedChars(&length, bufSize);
+  init2(buf, length, CODEC_JP2);
   free(buf);
 
   counter = 0;
@@ -143,30 +135,7 @@ error:
 }
 
 int JPXStream::lookChar() {
-  if (inited == gFalse) init();
-
-  if (!image) return EOF;
-
-  int w = image->comps[0].w;
-  int h = image->comps[0].h;
-
-  int y = (counter / image->numcomps) / w;
-  int x = (counter / image->numcomps) % w;
-  if (y >= h) return EOF;
-
-  int component = counter % image->numcomps;
-
-  int adjust = 0;
-  if (image->comps[component].prec > 8) {
-    adjust = image->comps[component].prec - 8;
-  }
-
-  int r = image->comps[component].data[y * w + x];
-  r += (image->comps[component].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
-
-  unsigned char rc = (unsigned char) ((r >> adjust)+((r >> (adjust-1))%2));
-
-  return rc;
+  return doLookChar();
 }
 
 GooString *JPXStream::getPSFilter(int psLevel, char *indent) {
diff --git a/poppler/JPEG2000Stream.h b/poppler/JPEG2000Stream.h
index ea32093..adec1c3 100644
--- a/poppler/JPEG2000Stream.h
+++ b/poppler/JPEG2000Stream.h
@@ -4,7 +4,7 @@
 //
 // A JPX stream decoder using OpenJPEG
 //
-// Copyright 2008 Albert Astals Cid <aacid at kde.org>
+// Copyright 2008, 2010 Albert Astals Cid <aacid at kde.org>
 //
 // Licensed under GPLv2 or later
 //
@@ -39,6 +39,42 @@ private:
   void init();
   void init2(unsigned char *buf, int bufLen, OPJ_CODEC_FORMAT format);
 
+  virtual GBool hasGetChars() { return true; }
+  virtual int getChars(int nChars, Guchar *buffer);
+
+  inline int doGetChar() {
+    int result = doLookChar();
+    ++counter;
+    return result;
+  }
+
+  inline int doLookChar() {
+    if (inited == gFalse) init();
+
+    if (!image) return EOF;
+
+    int w = image->comps[0].w;
+    int h = image->comps[0].h;
+
+    int y = (counter / image->numcomps) / w;
+    int x = (counter / image->numcomps) % w;
+    if (y >= h) return EOF;
+
+    int component = counter % image->numcomps;
+
+    int adjust = 0;
+    if (image->comps[component].prec > 8) {
+      adjust = image->comps[component].prec - 8;
+    }
+
+    int r = image->comps[component].data[y * w + x];
+    r += (image->comps[component].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
+
+    unsigned char rc = (unsigned char) ((r >> adjust)+((r >> (adjust-1))%2));
+
+    return rc;
+  }
+
   opj_image_t *image;
   opj_dinfo_t *dinfo;
   int counter;
diff --git a/poppler/Link.cc b/poppler/Link.cc
index 5d7b779..b6d7f2d 100644
--- a/poppler/Link.cc
+++ b/poppler/Link.cc
@@ -16,7 +16,7 @@
 // Copyright (C) 2006, 2008 Pino Toscano <pino at kde.org>
 // Copyright (C) 2007,2010 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2008 Hugo Mercier <hmercier31 at gmail.com>
-// Copyright (C) 2008, 2009 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2008-2010 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2009 Kovid Goyal <kovid at kovidgoyal.net>
 // Copyright (C) 2009 Ilya Gorenbein <igorenbein at finjan.com>
 //
@@ -704,11 +704,7 @@ LinkRendition::LinkRendition(Object *obj) {
       } else if (tmp.isStream()) {
         Stream *stream = tmp.getStream();
 	js = new GooString();
-	stream->reset();
-	int i;
-	while ((i = stream->getChar()) != EOF) {
-	  js->append((char)i);
-	}
+	stream->fillGooString(js);
       } else {
         error(-1, "Invalid Rendition Action: JS not string or stream");
       }
@@ -766,11 +762,7 @@ LinkJavaScript::LinkJavaScript(Object *jsObj) {
   else if (jsObj->isStream()) {
     Stream *stream = jsObj->getStream();
     js = new GooString();
-    stream->reset();
-    int i;
-    while ((i = stream->getChar()) != EOF) {
-      js->append((char)i);
-    }
+    stream->fillGooString(js);
   }
 }
 
diff --git a/poppler/Object.h b/poppler/Object.h
index 3038d0c..6d60d0f 100644
--- a/poppler/Object.h
+++ b/poppler/Object.h
@@ -223,6 +223,7 @@ public:
   void streamReset();
   void streamClose();
   int streamGetChar();
+  int streamGetChars(int nChars, Guchar *buffer);
   int streamLookChar();
   char *streamGetLine(char *buf, int size);
   Guint streamGetPos();
@@ -334,6 +335,9 @@ inline void Object::streamClose()
 inline int Object::streamGetChar()
   { OBJECT_TYPE_CHECK(objStream); return stream->getChar(); }
 
+inline int Object::streamGetChars(int nChars, Guchar *buffer)
+  { OBJECT_TYPE_CHECK(objStream); return stream->doGetChars(nChars, buffer); }
+
 inline int Object::streamLookChar()
   { OBJECT_TYPE_CHECK(objStream); return stream->lookChar(); }
 
diff --git a/poppler/Stream.cc b/poppler/Stream.cc
index 0771e25..988f99a 100644
--- a/poppler/Stream.cc
+++ b/poppler/Stream.cc
@@ -14,7 +14,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2005 Jeff Muizelaar <jeff at infidigm.net>
-// Copyright (C) 2006-2009 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2006-2010 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2007 Krzysztof Kowalczyk <kkowalczyk at gmail.com>
 // Copyright (C) 2008 Julien Rebetez <julien at fhtagn.net>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
@@ -99,6 +99,15 @@ int Stream::getRawChar() {
   return EOF;
 }
 
+int Stream::getChars(int nChars, Guchar *buffer) {
+  error(-1, "Internal: called getChars() on non-predictor stream");
+  return 0;
+}
+
+void Stream::getRawChars(int nChars, int *buffer) {
+  error(-1, "Internal: called getRawChars() on non-predictor stream");
+}
+
 char *Stream::getLine(char *buf, int size) {
   int i;
   int c;
@@ -461,9 +470,8 @@ Guchar *ImageStream::getLine() {
     }
   } else if (nBits == 8) {
     Guchar *line = imgLine;
-    for (i = 0; i < nVals; ++i) {
-      *line++ = str->getChar();
-    }
+    int readChars = str->doGetChars(nVals, line);
+    for ( ; readChars < nVals; readChars++) line[readChars] = EOF;
   } else if (nBits == 16) {
     // this is a hack to support 16 bits images, everywhere
     // we assume a component fits in 8 bits, with this hack
@@ -543,12 +551,17 @@ int StreamPredictor::lookChar() {
 }
 
 int StreamPredictor::getChar() {
-  if (predIdx >= rowBytes) {
-    if (!getNextLine()) {
-      return EOF;
-    }
+  return doGetChar();
+}
+
+int StreamPredictor::getChars(int nChars, Guchar *buffer)
+{
+  for (int i = 0; i < nChars; ++i) {
+    const int c = doGetChar();
+    if (likely(c != EOF)) buffer[i] = c;
+    else return i;
   }
-  return predLine[predIdx++];
+  return nChars;
 }
 
 GBool StreamPredictor::getNextLine() {
@@ -571,13 +584,15 @@ GBool StreamPredictor::getNextLine() {
   }
 
   // read the raw line, apply PNG (byte) predictor
+  int *rawCharLine = new int[rowBytes - pixBytes];
+  str->getRawChars(rowBytes - pixBytes, rawCharLine);
   memset(upLeftBuf, 0, pixBytes + 1);
   for (i = pixBytes; i < rowBytes; ++i) {
     for (j = pixBytes; j > 0; --j) {
       upLeftBuf[j] = upLeftBuf[j-1];
     }
     upLeftBuf[0] = predLine[i];
-    if ((c = str->getRawChar()) == EOF) {
+    if ((c = rawCharLine[i - pixBytes]) == EOF) {
       if (i > pixBytes) {
 	// this ought to return false, but some (broken) PDF files
 	// contain truncated image data, and Adobe apparently reads the
@@ -621,6 +636,7 @@ GBool StreamPredictor::getNextLine() {
       break;
     }
   }
+  delete[] rawCharLine;
 
   // apply TIFF (component) predictor
   if (predictor == 2) {
@@ -1237,16 +1253,13 @@ int LZWStream::lookChar() {
   return seqBuf[seqIndex];
 }
 
+void LZWStream::getRawChars(int nChars, int *buffer) {
+  for (int i = 0; i < nChars; ++i)
+    buffer[i] = doGetRawChar();
+}
+
 int LZWStream::getRawChar() {
-  if (eof) {
-    return EOF;
-  }
-  if (seqIndex >= seqLength) {
-    if (!processNextCode()) {
-      return EOF;
-    }
-  }
-  return seqBuf[seqIndex++];
+  return doGetRawChar();
 }
 
 void LZWStream::reset() {
@@ -4231,20 +4244,20 @@ void FlateStream::reset() {
 }
 
 int FlateStream::getChar() {
-  int c;
+  return doGetChar();
+}
 
+int FlateStream::getChars(int nChars, Guchar *buffer) {
   if (pred) {
-    return pred->getChar();
-  }
-  while (remain == 0) {
-    if (endOfBlock && eof)
-      return EOF;
-    readSome();
+    return pred->getChars(nChars, buffer);
+  } else {
+    for (int i = 0; i < nChars; ++i) {
+      const int c = doGetChar();
+      if (likely(c != EOF)) buffer[i] = c;
+      else return i;
+    }
+    return nChars;
   }
-  c = buf[index];
-  index = (index + 1) & flateMask;
-  --remain;
-  return c;
 }
 
 int FlateStream::lookChar() {
@@ -4262,18 +4275,13 @@ int FlateStream::lookChar() {
   return c;
 }
 
-int FlateStream::getRawChar() {
-  int c;
+void FlateStream::getRawChars(int nChars, int *buffer) {
+  for (int i = 0; i < nChars; ++i)
+    buffer[i] = doGetRawChar();
+}
 
-  while (remain == 0) {
-    if (endOfBlock && eof)
-      return EOF;
-    readSome();
-  }
-  c = buf[index];
-  index = (index + 1) & flateMask;
-  --remain;
-  return c;
+int FlateStream::getRawChar() {
+  return doGetRawChar();
 }
 
 GooString *FlateStream::getPSFilter(int psLevel, char *indent) {
diff --git a/poppler/Stream.h b/poppler/Stream.h
index 49ae8fb..583278f 100644
--- a/poppler/Stream.h
+++ b/poppler/Stream.h
@@ -15,7 +15,7 @@
 //
 // Copyright (C) 2005 Jeff Muizelaar <jeff at infidigm.net>
 // Copyright (C) 2008 Julien Rebetez <julien at fhtagn.net>
-// Copyright (C) 2008 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2008, 2010 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2009 Stefan Thomas <thomas at eload24.com>
 // Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
@@ -106,6 +106,56 @@ public:
   // Close down the stream.
   virtual void close();
 
+  inline int doGetChars(int nChars, Guchar *buffer)
+  {
+    if (hasGetChars()) {
+      return getChars(nChars, buffer);
+    } else {
+      for (int i = 0; i < nChars; ++i) {
+        const int c = getChar();
+        if (likely(c != EOF)) buffer[i] = c;
+        else return i;
+      }
+      return nChars;
+    }
+  }
+
+  inline void fillGooString(GooString *s)
+  {
+    Guchar readBuf[4096];
+    int readChars;
+    reset();
+    while ((readChars = doGetChars(4096, readBuf)) != 0) {
+      s->append((const char *)readBuf, readChars);
+    }
+  }
+  
+  inline Guchar *toUnsignedChars(int *length, int initialSize = 4096, int sizeIncrement = 4096)
+  {
+    int readChars;
+    Guchar *buf = (Guchar *)gmalloc(initialSize);
+    int size = initialSize;
+    *length = 0;
+    int charsToRead = initialSize;
+    bool continueReading = true;
+    reset();
+    while (continueReading && (readChars = doGetChars(charsToRead, &buf[*length])) != 0) {
+      *length += readChars;
+      if (readChars == charsToRead) {
+        if (lookChar() != EOF) {
+          size += sizeIncrement;
+          charsToRead = initialSize;
+          buf = (Guchar *)grealloc(buf, size);
+        } else {
+          continueReading = false;
+        }
+      } else {
+        continueReading = false;
+      }
+    }
+    return buf;
+  }
+
   // Get next char from stream.
   virtual int getChar() = 0;
 
@@ -115,6 +165,7 @@ public:
   // Get next char from stream without using the predictor.
   // This is only used by StreamPredictor.
   virtual int getRawChar();
+  virtual void getRawChars(int nChars, int *buffer);
 
   // Get next char directly from stream source, without filtering it
   virtual int getUnfilteredChar () = 0;
@@ -166,6 +217,8 @@ public:
   Stream *addFilters(Object *dict);
 
 private:
+  virtual GBool hasGetChars() { return false; }
+  virtual int getChars(int nChars, Guchar *buffer);
 
   Stream *makeFilter(char *name, Stream *str, Object *params);
 
@@ -347,11 +400,21 @@ public:
 
   int lookChar();
   int getChar();
+  int getChars(int nChars, Guchar *buffer);
 
 private:
 
   GBool getNextLine();
 
+  inline int doGetChar() {
+    if (predIdx >= rowBytes) {
+      if (!getNextLine()) {
+        return EOF;
+      }
+    }
+    return predLine[predIdx++];
+  }
+
   Stream *str;			// base stream
   int predictor;		// predictor
   int width;			// pixels per line
@@ -383,7 +446,7 @@ public:
   virtual void reset();
   virtual void close();
   virtual int getChar()
-    { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
+    { return doGetChar(); }
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
   virtual int getPos() { return bufPos + (bufPtr - buf); }
@@ -397,6 +460,20 @@ public:
 private:
 
   GBool fillBuf();
+  
+  inline int doGetChar()
+    { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
+
+  virtual GBool hasGetChars() { return true; }
+  virtual int getChars(int nChars, Guchar *buffer)
+    {
+      for (int i = 0; i < nChars; ++i) {
+        const int c = doGetChar();
+        if (likely(c != EOF)) buffer[i] = c;
+        else return i;
+      }
+      return nChars;
+    }
 
   FILE *f;
   Guint start;
@@ -596,11 +673,24 @@ public:
   virtual int getChar();
   virtual int lookChar();
   virtual int getRawChar();
+  virtual void getRawChars(int nChars, int *buffer);
   virtual GooString *getPSFilter(int psLevel, char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
 
+  inline int doGetRawChar() {
+    if (eof) {
+      return EOF;
+    }
+    if (seqIndex >= seqLength) {
+      if (!processNextCode()) {
+        return EOF;
+      }
+    }
+    return seqBuf[seqIndex++];
+  }
+
   StreamPredictor *pred;	// predictor
   int early;			// early parameter
   GBool eof;			// true if at eof
@@ -855,11 +945,35 @@ public:
   virtual int getChar();
   virtual int lookChar();
   virtual int getRawChar();
+  virtual void getRawChars(int nChars, int *buffer);
   virtual GooString *getPSFilter(int psLevel, char *indent);
   virtual GBool isBinary(GBool last = gTrue);
   virtual void unfilteredReset ();
 
 private:
+  inline int doGetRawChar() {
+    int c;
+
+    while (remain == 0) {
+      if (endOfBlock && eof)
+        return EOF;
+      readSome();
+    }
+    c = buf[index];
+    index = (index + 1) & flateMask;
+    --remain;
+    return c;
+  }
+
+  inline int doGetChar() {
+    if (pred) {
+      return pred->getChar();
+    }
+    return doGetRawChar();
+  }
+
+  virtual GBool hasGetChars() { return true; }
+  virtual int getChars(int nChars, Guchar *buffer);
 
   StreamPredictor *pred;	// predictor
   Guchar buf[flateWindow];	// output data buffer


More information about the poppler mailing list