[poppler] poppler/CairoOutputDev.cc poppler/CairoOutputDev.h poppler/JBIG2Stream.cc poppler/JBIG2Stream.h poppler/Stream.cc

Adrian Johnson ajohnson at kemper.freedesktop.org
Fri Jan 23 03:55:11 PST 2015


 poppler/CairoOutputDev.cc |  117 ++++++++++++++++++++++++++++++++++++++--------
 poppler/CairoOutputDev.h  |    3 +
 poppler/JBIG2Stream.cc    |    9 ++-
 poppler/JBIG2Stream.h     |    4 +
 poppler/Stream.cc         |   13 ++++-
 5 files changed, 121 insertions(+), 25 deletions(-)

New commits:
commit f932315e559a7857d9c5642eb04efc0d2b717789
Author: suzuki toshiya <mpsuzuki at hiroshima-u.ac.jp>
Date:   Tue Jan 20 22:05:29 2015 +1030

    cairo: support embedding JBIG2 image data
    
    http://lists.freedesktop.org/archives/poppler/2014-December/011183.html

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 4e8abcf..a770320 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -63,6 +63,7 @@
 #include "CairoFontEngine.h"
 #include "CairoRescaleBox.h"
 #include "UnicodeMap.h"
+#include "JBIG2Stream.h"
 //------------------------------------------------------------------------
 
 // #define LOG_CAIRO
@@ -2701,6 +2702,68 @@ static GBool colorMapHasIdentityDecodeMap(GfxImageColorMap *colorMap)
   return gTrue;
 }
 
+#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 2)
+static cairo_status_t setMimeIdFromRef(cairo_surface_t *surface,
+				       const char *mime_type,
+				       const char *mime_id_prefix,
+				       Ref ref)
+{
+  GooString *mime_id;
+  char *idBuffer;
+  cairo_status_t status;
+
+  mime_id = new GooString;
+
+  if (mime_id_prefix)
+    mime_id->append(mime_id_prefix);
+
+  mime_id->appendf("{0:d}-{1:d}", ref.gen, ref.num);
+
+  idBuffer = copyString(mime_id->getCString());
+  status = cairo_surface_set_mime_data (surface, mime_type,
+                                        (const unsigned char *)idBuffer,
+                                        mime_id->getLength(),
+                                        gfree, idBuffer);
+  delete mime_id;
+  if (status)
+    gfree (idBuffer);
+  return status;
+}
+#endif
+
+#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0)
+GBool CairoOutputDev::setMimeDataForJBIG2Globals(Stream  *str,
+                                                 cairo_surface_t *image)
+{
+  JBIG2Stream *jb2Str = static_cast<JBIG2Stream *>(str);
+  Object* globalsStr = jb2Str->getGlobalsStream();
+  char *globalsBuffer;
+  int globalsLength;
+
+  // nothing to do for JBIG2 stream without Globals
+  if (!globalsStr->isStream())
+    return gTrue;
+
+  if (setMimeIdFromRef(image, CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID, NULL,
+                       jb2Str->getGlobalsStreamRef()))
+    return gFalse;
+
+  if (!getStreamData(globalsStr->getStream(), &globalsBuffer, &globalsLength))
+    return gFalse;
+
+  if (cairo_surface_set_mime_data (image, CAIRO_MIME_TYPE_JBIG2_GLOBAL,
+                                   (const unsigned char*)globalsBuffer,
+                                   globalsLength,
+                                   gfree, (void*)globalsBuffer))
+  {
+    gfree (globalsBuffer);
+    return gFalse;
+  }
+
+  return gTrue;
+}
+#endif
+
 void CairoOutputDev::setMimeData(GfxState *state, Stream *str, Object *ref,
 				 GfxImageColorMap *colorMap, cairo_surface_t *image)
 {
@@ -2708,17 +2771,35 @@ void CairoOutputDev::setMimeData(GfxState *state, Stream *str, Object *ref,
   int len;
   Object obj;
   GfxColorSpace *colorSpace;
+  StreamKind  strKind = str->getKind();
+  const char *mime_type;
 
-  if (!printing || !(str->getKind() == strDCT || str->getKind() == strJPX))
+  if (!printing)
     return;
 
+  switch (strKind) {
+    case strDCT:
+      mime_type = CAIRO_MIME_TYPE_JPEG;
+      break;
+    case strJPX:
+      mime_type = CAIRO_MIME_TYPE_JP2;
+      break;
+#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0)
+    case strJBIG2:
+      mime_type = CAIRO_MIME_TYPE_JBIG2;
+      break;
+#endif
+    default:
+      return;
+  }
+
   str->getDict()->lookup("ColorSpace", &obj);
   colorSpace = GfxColorSpace::parse(NULL, &obj, this, state);
   obj.free();
 
   // colorspace in stream dict may be different from colorspace in jpx
   // data
-  if (str->getKind() == strJPX && colorSpace)
+  if (strKind == strJPX && colorSpace)
     return;
 
   // only embed mime data for gray, rgb, and cmyk colorspaces.
@@ -2746,31 +2827,27 @@ void CairoOutputDev::setMimeData(GfxState *state, Stream *str, Object *ref,
   if (!colorMapHasIdentityDecodeMap(colorMap))
     return;
 
+#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0)
+  if (strKind == strJBIG2 && !setMimeDataForJBIG2Globals(str, image))
+    return;
+#endif
+
   if (getStreamData (str->getNextStream(), &strBuffer, &len)) {
-    cairo_status_t st;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
 #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 2)
     if (ref && ref->isRef()) {
-      Ref imgRef = ref->getRef();
-      GooString *surfaceId = new GooString("poppler-surface-");
-      surfaceId->appendf("{0:d}-{1:d}", imgRef.gen, imgRef.num);
-      char *idBuffer = copyString(surfaceId->getCString());
-      st = cairo_surface_set_mime_data (image, CAIRO_MIME_TYPE_UNIQUE_ID,
-                                        (const unsigned char *)idBuffer,
-                                        surfaceId->getLength(),
-                                        gfree, idBuffer);
-      if (st)
-        gfree(idBuffer);
-      delete surfaceId;
+      status = setMimeIdFromRef(image, CAIRO_MIME_TYPE_UNIQUE_ID,
+                                "poppler-surface-", ref->getRef());
     }
 #endif
+    if (!status) {
+      status = cairo_surface_set_mime_data (image, mime_type,
+					    (const unsigned char *)strBuffer, len,
+					    gfree, strBuffer);
+    }
 
-    st = cairo_surface_set_mime_data (image,
-				      str->getKind() == strDCT ?
-				      CAIRO_MIME_TYPE_JPEG : CAIRO_MIME_TYPE_JP2,
-				      (const unsigned char *)strBuffer, len,
-				      gfree, strBuffer);
-    if (st)
+    if (status)
       gfree (strBuffer);
   }
 }
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index 8de391a..cc29846 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -280,6 +280,9 @@ protected:
 		   GfxImageColorMap *colorMap, cairo_surface_t *image);
   void fillToStrokePathClip(GfxState *state);
   void alignStrokeCoords(GfxSubpath *subpath, int i, double *x, double *y);
+#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0)
+  GBool setMimeDataForJBIG2Globals (Stream *str, cairo_surface_t *image);
+#endif
 
   GfxRGB fill_color, stroke_color;
   cairo_pattern_t *fill_pattern, *stroke_pattern;
diff --git a/poppler/JBIG2Stream.cc b/poppler/JBIG2Stream.cc
index 0695dc5..8e1c12f 100644
--- a/poppler/JBIG2Stream.cc
+++ b/poppler/JBIG2Stream.cc
@@ -1168,7 +1168,7 @@ JBIG2CodeTable::~JBIG2CodeTable() {
 // JBIG2Stream
 //------------------------------------------------------------------------
 
-JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStreamA):
+JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStreamA, Object *globalsStreamRefA):
   FilterStream(strA)
 {
   pageBitmap = NULL;
@@ -1193,7 +1193,12 @@ JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStreamA):
   huffDecoder = new JBIG2HuffmanDecoder();
   mmrDecoder = new JBIG2MMRDecoder();
 
-  globalsStreamA->copy(&globalsStream);
+  if (globalsStreamA->isStream()) {
+    globalsStreamA->copy(&globalsStream);
+    if (globalsStreamRefA->isRef())
+      globalsStreamRef = globalsStreamRefA->getRef();
+  }
+
   segments = globalSegments = NULL;
   curStr = NULL;
   dataPtr = dataEnd = NULL;
diff --git a/poppler/JBIG2Stream.h b/poppler/JBIG2Stream.h
index 0ee2518..7ffc441 100644
--- a/poppler/JBIG2Stream.h
+++ b/poppler/JBIG2Stream.h
@@ -46,7 +46,7 @@ class JBIG2MMRDecoder;
 class JBIG2Stream: public FilterStream {
 public:
 
-  JBIG2Stream(Stream *strA, Object *globalsStreamA);
+  JBIG2Stream(Stream *strA, Object *globalsStreamA, Object *globalsStreamRefA);
   virtual ~JBIG2Stream();
   virtual StreamKind getKind() { return strJBIG2; }
   virtual void reset();
@@ -57,6 +57,7 @@ public:
   virtual GooString *getPSFilter(int psLevel, const char *indent);
   virtual GBool isBinary(GBool last = gTrue);
   virtual Object *getGlobalsStream() { return &globalsStream; }
+  virtual Ref getGlobalsStreamRef() { return globalsStreamRef; }
 
 private:
   virtual GBool hasGetChars() { return true; }
@@ -132,6 +133,7 @@ private:
   GBool readLong(int *x);
 
   Object globalsStream;
+  Ref globalsStreamRef;
   Guint pageW, pageH, curPageH;
   Guint pageDefPixel;
   JBIG2Bitmap *pageBitmap;
diff --git a/poppler/Stream.cc b/poppler/Stream.cc
index 4c00ddb..8996e29 100644
--- a/poppler/Stream.cc
+++ b/poppler/Stream.cc
@@ -59,6 +59,7 @@
 #include "Lexer.h"
 #include "GfxState.h"
 #include "Stream.h"
+#include "XRef.h"
 #include "JBIG2Stream.h"
 #include "Stream-CCITT.h"
 #include "CachedFile.h"
@@ -337,10 +338,18 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params, int recursio
     str = new FlateStream(str, pred, columns, colors, bits);
   } else if (!strcmp(name, "JBIG2Decode")) {
     if (params->isDict()) {
-      params->dictLookup("JBIG2Globals", &globals, recursion);
+      XRef *xref = params->getDict()->getXRef();
+      params->dictLookupNF("JBIG2Globals", &globals);
+      while (globals.isRef()) {
+        obj.free();
+        globals.copy(&obj);
+        globals.free();
+        obj.fetch(xref, &globals);
+      }
     }
-    str = new JBIG2Stream(str, &globals);
+    str = new JBIG2Stream(str, &globals, &obj);
     globals.free();
+    obj.free();
   } else if (!strcmp(name, "JPXDecode")) {
     str = new JPXStream(str);
   } else if (!strcmp(name, "Crypt")) {


More information about the poppler mailing list