[poppler] 3 commits - CMakeLists.txt poppler/Function.cc poppler/Function.h poppler/GfxState.cc poppler/GfxState.h poppler/Makefile.am poppler/PopplerCache.cc poppler/PopplerCache.h

Albert Astals Cid aacid at kemper.freedesktop.org
Sun Jun 7 04:39:20 PDT 2009


 CMakeLists.txt          |    1 
 poppler/Function.cc     |   76 +++++++++++++++++++++++++++++++++++++
 poppler/Function.h      |    2 
 poppler/GfxState.cc     |   97 ++++++++++++++++++++++--------------------------
 poppler/GfxState.h      |   19 +--------
 poppler/Makefile.am     |    1 
 poppler/PopplerCache.cc |   82 ++++++++++++++++++++++++++++++++++++++++
 poppler/PopplerCache.h  |   47 +++++++++++++++++++++++
 8 files changed, 258 insertions(+), 67 deletions(-)

New commits:
commit 3d40dcad850a2bc0e28845a15722db0c79920135
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sun Jun 7 13:38:50 2009 +0200

    Move the GfxState cache to the new poppler cache class

diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index d75e015..932bfff 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -43,6 +43,7 @@
 #include "GfxState_helpers.h"
 #include "GfxFont.h"
 #include "GlobalParams.h"
+#include "PopplerCache.h"
 
 //------------------------------------------------------------------------
 
@@ -1351,6 +1352,38 @@ void GfxLabColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
 // GfxICCBasedColorSpace
 //------------------------------------------------------------------------
 
+class GfxICCBasedColorSpaceKey : public PopplerCacheKey
+{
+  public:
+    GfxICCBasedColorSpaceKey(int numA, int genA) : num(numA), gen(genA)
+    {
+    }
+    
+    bool operator==(const PopplerCacheKey &key) const
+    {
+      const GfxICCBasedColorSpaceKey *k = static_cast<const GfxICCBasedColorSpaceKey*>(&key);
+      return k->num == num && k->gen == gen;
+    }
+    
+    int num, gen;
+};
+
+class GfxICCBasedColorSpaceItem : public PopplerCacheItem
+{
+  public:
+    GfxICCBasedColorSpaceItem(GfxICCBasedColorSpace *csA)
+    {
+      cs = static_cast<GfxICCBasedColorSpace*>(csA->copy());
+    }
+    
+    ~GfxICCBasedColorSpaceItem()
+    {
+      delete cs;
+    }
+    
+    GfxICCBasedColorSpace *cs;
+};
+
 GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA,
 					     Ref *iccProfileStreamA) {
   nComps = nCompsA;
@@ -1413,9 +1446,15 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
   obj1.free();
 #ifdef USE_CMS
   // check cache
-  if (iccProfileStreamA.num > 0
-     && (cs = GfxICCBasedCache::lookup(iccProfileStreamA.num,
-          iccProfileStreamA.gen)) != NULL) return cs;
+  if (iccProfileStreamA.num > 0) {
+    GfxICCBasedColorSpaceKey k(iccProfileStreamA.num, iccProfileStreamA.gen);
+    GfxICCBasedColorSpaceItem *item = static_cast<GfxICCBasedColorSpaceItem *>(cache->lookup(k));
+    if (item != NULL)
+    {
+      cs = static_cast<GfxICCBasedColorSpace*>(item->cs->copy());
+      return cs;
+    }
+  }
 #endif
   arr->get(1, &obj1);
   if (!obj1.isStream()) {
@@ -1529,7 +1568,9 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
   obj1.free();
   // put this colorSpace into cache
   if (iccProfileStreamA.num > 0) {
-    GfxICCBasedCache::put(iccProfileStreamA.num,iccProfileStreamA.gen,cs);
+    GfxICCBasedColorSpaceKey *k = new GfxICCBasedColorSpaceKey(iccProfileStreamA.num, iccProfileStreamA.gen);
+    GfxICCBasedColorSpaceItem *item = new GfxICCBasedColorSpaceItem(cs);
+    cache->put(k, item);
   }
 #endif
   return cs;
@@ -1670,53 +1711,7 @@ void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow,
 }
 
 #ifdef USE_CMS
-GfxICCBasedCache
-   GfxICCBasedCache::cache[GFX_ICCBASED_CACHE_SIZE];
-
-GfxICCBasedCache::GfxICCBasedCache()
-{
-  num = 0;
-  gen = 0;
-  colorSpace = 0;
-}
-
-GfxICCBasedColorSpace *GfxICCBasedCache::lookup(int numA, int genA)
-{
-  int i;
-
-  if (cache[0].num == numA && cache[0].gen == genA) {
-    return (GfxICCBasedColorSpace *)cache[0].colorSpace->copy();
-  }
-  for (i = 1;i < GFX_ICCBASED_CACHE_SIZE && cache[i].num > 0;i++) {
-    if (cache[i].num == numA && cache[i].gen == genA) {
-      int j;
-      GfxICCBasedCache hit = cache[i];
-
-      for (j = i;j > 0;j--) {
-	if (cache[j - 1].num > 0) cache[j] = cache[j-1];
-      }
-      cache[0] = hit;
-      return (GfxICCBasedColorSpace *)hit.colorSpace->copy();
-    }
-  }
-  return NULL;
-}
-
-void GfxICCBasedCache::put(int numA, int genA,
-  GfxICCBasedColorSpace *cs)
-{
-  int i;
-
-  if (cache[GFX_ICCBASED_CACHE_SIZE-1].num > 0) {
-    delete cache[GFX_ICCBASED_CACHE_SIZE-1].colorSpace;
-  }
-  for (i = GFX_ICCBASED_CACHE_SIZE-1; i > 0; i--) {
-    if (cache[i - 1].num > 0) cache[i] = cache[i - 1];
-  }
-  cache[0].num = numA;
-  cache[0].gen = genA;
-  cache[0].colorSpace = (GfxICCBasedColorSpace *)cs->copy();
-}
+PopplerCache *GfxICCBasedColorSpace::cache = new PopplerCache(5);
 #endif
 
 //------------------------------------------------------------------------
diff --git a/poppler/GfxState.h b/poppler/GfxState.h
index 09abc2f..6c8be49 100644
--- a/poppler/GfxState.h
+++ b/poppler/GfxState.h
@@ -38,6 +38,7 @@ class Array;
 class GfxFont;
 class PDFRectangle;
 class GfxShading;
+class PopplerCache;
 
 class Matrix {
 public:
@@ -458,24 +459,10 @@ private:
 #ifdef USE_CMS
   GfxColorTransform *transform;
   GfxColorTransform *lineTransform; // color transform for line
-#endif
-};
 
-#ifdef USE_CMS
-#define GFX_ICCBASED_CACHE_SIZE 5
-class GfxICCBasedCache {
-public:
-  static GfxICCBasedColorSpace *lookup(int numA, int genA);
-  static void put(int numA, int genA, GfxICCBasedColorSpace *cs);
-private:
-  GfxICCBasedCache();
-  int num;
-  int gen;
-  GfxICCBasedColorSpace *colorSpace;
-  static GfxICCBasedCache cache[GFX_ICCBASED_CACHE_SIZE];
-};
+  static PopplerCache *cache;
 #endif
-
+};
 //------------------------------------------------------------------------
 // GfxIndexedColorSpace
 //------------------------------------------------------------------------
commit 2619e09833f421fb3d8cc68d41d15081ae6824e4
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sun Jun 7 13:37:40 2009 +0200

    Implement a cache for PostscriptFunction transforms
    
    Makes time of rendering of bug 21562 go down from 24 to 8 seconds

diff --git a/poppler/Function.cc b/poppler/Function.cc
index b538f5f..f81f0fd 100644
--- a/poppler/Function.cc
+++ b/poppler/Function.cc
@@ -37,6 +37,7 @@
 #include "Stream.h"
 #include "Error.h"
 #include "Function.h"
+#include "PopplerCache.h"
 
 #ifndef M_PI
 #define M_PI 3.14159265358979323846
@@ -1009,6 +1010,64 @@ void PSStack::roll(int n, int j) {
   }
 }
 
+class PostScriptFunctionKey : public PopplerCacheKey
+{
+  public:
+    PostScriptFunctionKey(int sizeA, double *inA, bool copyA)
+    {
+      copied = copyA;
+      size = sizeA;
+      if (copied) {
+        in = new double[size];
+        for (int i = 0; i < size; ++i) in[i] = inA[i];
+      } else {
+        in = inA;
+      }
+    }
+    
+    ~PostScriptFunctionKey()
+    {
+      if (copied) delete[] in;
+    }
+       
+    bool operator==(const PopplerCacheKey &key) const
+    {
+      const PostScriptFunctionKey *k = static_cast<const PostScriptFunctionKey*>(&key);
+      if (size == k->size) {
+        bool equal = true;
+        for (int i = 0; equal && i < size; ++i) {
+          equal = in[i] == k->in[i];
+        }
+        return equal;
+      } else {
+        return false;
+      }
+    }
+  
+    bool copied;
+    int size;
+    double *in;
+};
+
+class PostScriptFunctionItem : public PopplerCacheItem
+{
+  public:
+    PostScriptFunctionItem(int sizeA, double *outA)
+    {
+      size = sizeA;
+      out = new double[size];
+      for (int i = 0; i < size; ++i) out[i] = outA[i];
+    }
+    
+    ~PostScriptFunctionItem()
+    {
+      delete[] out;
+    }
+    
+    int size;
+    double *out;
+};
+
 PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
   Stream *str;
   int codePtr;
@@ -1018,6 +1077,7 @@ PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
   codeString = NULL;
   codeSize = 0;
   ok = gFalse;
+  cache = new PopplerCache(5);
 
   //----- initialize the generic stuff
   if (!init(dict)) {
@@ -1075,10 +1135,21 @@ PostScriptFunction::~PostScriptFunction() {
   gfree(code);
   delete codeString;
   delete stack;
+  delete cache;
 }
 
 void PostScriptFunction::transform(double *in, double *out) {
   int i;
+  
+  PostScriptFunctionKey key(m, in, false);
+  PopplerCacheItem *item = cache->lookup(key);
+  if (item) {
+    PostScriptFunctionItem *it = static_cast<PostScriptFunctionItem *>(item);
+    for (int i = 0; i < n; ++i) {
+      out[i] = it->out[i];
+    }
+    return;
+  }
 
   stack->clear();
   for (i = 0; i < m; ++i) {
@@ -1094,6 +1165,11 @@ void PostScriptFunction::transform(double *in, double *out) {
       out[i] = range[i][1];
     }
   }
+
+  PostScriptFunctionKey *newKey = new PostScriptFunctionKey(m, in, true);
+  PostScriptFunctionItem *newItem = new PostScriptFunctionItem(n, out);
+  cache->put(newKey, newItem);
+  
   // if (!stack->empty()) {
   //   error(-1, "Extra values on stack at end of PostScript function");
   // }
diff --git a/poppler/Function.h b/poppler/Function.h
index 4cf6fd0..2dcccb0 100644
--- a/poppler/Function.h
+++ b/poppler/Function.h
@@ -34,6 +34,7 @@ class Dict;
 class Stream;
 struct PSObject;
 class PSStack;
+class PopplerCache;
 
 //------------------------------------------------------------------------
 // Function
@@ -237,6 +238,7 @@ private:
   PSStack *stack;
   int codeSize;
   GBool ok;
+  PopplerCache *cache;
 };
 
 #endif
commit 588bfe3c14f42be492066c2a98e30482475a6926
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sun Jun 7 13:36:39 2009 +0200

    Add a code to a generic cache based on Koji's code for GfxState cache

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0fbc49a..194d46b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -182,6 +182,7 @@ set(poppler_SRCS
   poppler/Parser.cc
   poppler/PDFDoc.cc
   poppler/PDFDocEncoding.cc
+  poppler/PopplerCache.cc
   poppler/ProfileData.cc
   poppler/PreScanOutputDev.cc
   poppler/PSTokenizer.cc
diff --git a/poppler/Makefile.am b/poppler/Makefile.am
index 4f0f410..f43cf4b 100644
--- a/poppler/Makefile.am
+++ b/poppler/Makefile.am
@@ -255,6 +255,7 @@ libpoppler_la_SOURCES =		\
 	Parser.cc 		\
 	PDFDoc.cc 		\
 	PDFDocEncoding.cc	\
+	PopplerCache.cc		\
 	ProfileData.cc		\
 	PreScanOutputDev.cc \
 	PSTokenizer.cc		\
diff --git a/poppler/PopplerCache.cc b/poppler/PopplerCache.cc
new file mode 100644
index 0000000..10c5f99
--- /dev/null
+++ b/poppler/PopplerCache.cc
@@ -0,0 +1,82 @@
+//========================================================================
+//
+// PopplerCache.h
+//
+// This file is licensed under the GPLv2 or later
+//
+// Copyright (C) 2009 Koji Otani <sho at bbr.jp>
+// Copyright (C) 2009 Albert Astals Cid <aacid at kde.org>
+//
+//========================================================================
+
+#include "PopplerCache.h"
+
+PopplerCacheKey::~PopplerCacheKey()
+{
+}
+
+PopplerCacheItem::~PopplerCacheItem()
+{
+}
+
+PopplerCache::PopplerCache(int cacheSizeA)
+{
+  cacheSize = cacheSizeA;
+  keys = new PopplerCacheKey*[cacheSize];
+  items = new PopplerCacheItem*[cacheSize];
+  lastValidCacheIndex = -1;
+}
+
+PopplerCache::~PopplerCache()
+{
+  for (int i = 0; i <= lastValidCacheIndex; ++i) {
+    delete keys[i];
+    delete items[i];
+  }
+  delete[] keys;
+  delete[] items;
+}
+
+PopplerCacheItem *PopplerCache::lookup(const PopplerCacheKey &key)
+{
+  if (lastValidCacheIndex < 0)
+    return 0;
+
+  if (*keys[0] == key) {
+    return items[0];
+  }
+  for (int i = 1; i <= lastValidCacheIndex; i++) {
+    if (*keys[i] == key) {
+      PopplerCacheKey *keyHit = keys[i];
+      PopplerCacheItem *itemHit = items[i];
+
+      for (int j = i; j > 0; j--) {
+        keys[j] = keys[j - 1];
+        items[j] = items[j - 1];
+      }
+      
+      keys[0] = keyHit;
+      items[0] = itemHit;
+      return itemHit;
+    }
+  }
+  return 0;
+}
+
+void PopplerCache::put(PopplerCacheKey *key, PopplerCacheItem *item)
+{
+  int movingStartIndex = lastValidCacheIndex + 1;
+  if (lastValidCacheIndex == cacheSize - 1) {
+    delete keys[lastValidCacheIndex];
+    delete items[lastValidCacheIndex];
+    movingStartIndex = cacheSize - 1;
+  } else {
+    lastValidCacheIndex++;
+  }
+  for (int i = movingStartIndex; i > 0; i--) {
+    keys[i] = keys[i - 1];
+    items[i] = items[i - 1];
+  }
+  keys[0] = key;
+  items[0] = item;
+}
diff --git a/poppler/PopplerCache.h b/poppler/PopplerCache.h
new file mode 100644
index 0000000..7d72d76
--- /dev/null
+++ b/poppler/PopplerCache.h
@@ -0,0 +1,47 @@
+//========================================================================
+//
+// PopplerCache.h
+//
+// This file is licensed under the GPLv2 or later
+//
+// Copyright (C) 2009 Koji Otani <sho at bbr.jp>
+// Copyright (C) 2009 Albert Astals Cid <aacid at kde.org>
+//
+//========================================================================
+
+#ifndef POPPLER_CACHE_H
+#define POPPLER_CACHE_H
+
+class PopplerCacheItem
+{
+  public:
+   virtual ~PopplerCacheItem();
+};
+
+class PopplerCacheKey
+{
+  public:
+    virtual ~PopplerCacheKey();
+    virtual bool operator==(const PopplerCacheKey &key) const = 0;
+};
+
+class PopplerCache
+{
+  public:
+    PopplerCache(int cacheSizeA);
+    ~PopplerCache();
+    
+    /* The item returned is owned by the cache */
+    PopplerCacheItem *lookup(const PopplerCacheKey &key);
+    
+    /* The key and item pointers ownership is taken by the cache */
+    void put(PopplerCacheKey *key, PopplerCacheItem *item);
+  
+  private:
+    PopplerCacheKey **keys;
+    PopplerCacheItem **items;
+    int lastValidCacheIndex;
+    int cacheSize;
+};
+
+#endif


More information about the poppler mailing list