[poppler] glib/poppler-page.cc glib/poppler-page.h poppler/CairoOutputDev.cc poppler/CairoOutputDev.h

Carlos Garcia Campos carlosgc at kemper.freedesktop.org
Sat Jan 19 09:10:03 PST 2008


 glib/poppler-page.cc      |   81 +++++++++++++++-------------
 glib/poppler-page.h       |    6 +-
 poppler/CairoOutputDev.cc |  131 ++++++++++++++++++++++++++--------------------
 poppler/CairoOutputDev.h  |   12 +++-
 4 files changed, 135 insertions(+), 95 deletions(-)

New commits:
commit fcdd5c51f370d040ae57aa64801c9bd4dbe88752
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sat Jan 19 18:00:10 2008 +0100

    Do not render images when getting the image mapping, it can be done later on demand.

diff --git a/glib/poppler-page.cc b/glib/poppler-page.cc
index 13d639a..803effe 100644
--- a/glib/poppler-page.cc
+++ b/glib/poppler-page.cc
@@ -1106,11 +1106,18 @@ poppler_page_find_text (PopplerPage *page,
 #if defined (HAVE_CAIRO)
 
 static CairoImageOutputDev *
-poppler_page_get_image_output_dev (PopplerPage *page)
+poppler_page_get_image_output_dev (PopplerPage *page,
+				   GBool (*imgDrawDeviceCbk)(int img_id, void *data),
+				   void *imgDrawCbkData)
 {
   if (page->image_dev == NULL) {
     page->image_dev = new CairoImageOutputDev ();
 
+    if (imgDrawDeviceCbk) {
+      page->image_dev->setImageDrawDecideCbk (imgDrawDeviceCbk,
+					      imgDrawCbkData);
+    }
+
     if (page->gfx)
       delete page->gfx;
     page->gfx = page->page->createGfx(page->image_dev,
@@ -1127,33 +1134,12 @@ poppler_page_get_image_output_dev (PopplerPage *page)
   return page->image_dev;
 }
 
-static GdkPixbuf *
-poppler_page_image_pixbuf_create (PopplerPage *page,
-				  CairoImage  *image)
-{
-  GdkPixbuf *pixbuf;
-  cairo_surface_t *surface;
-
-  surface = image->getImage ();
-  
-  pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
-			   FALSE, 8,
-			   cairo_image_surface_get_width (surface),
-			   cairo_image_surface_get_height (surface));
-  
-  copy_cairo_surface_to_pixbuf (surface,
-				cairo_image_surface_get_data (surface),
-				pixbuf);
-
-  return pixbuf;
-}
-
 /**
  * poppler_page_get_image_mapping:
  * @page: A #PopplerPage
  *
  * Returns a list of #PopplerImageMapping items that map from a
- * location on @page to a #GdkPixbuf.  This list must be freed
+ * location on @page to an image of the page. This list must be freed
  * with poppler_page_free_image_mapping() when done.
  *
  * Return value: A #GList of #PopplerImageMapping
@@ -1167,7 +1153,7 @@ poppler_page_get_image_mapping (PopplerPage *page)
   
   g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
 
-  out = poppler_page_get_image_output_dev (page);
+  out = poppler_page_get_image_output_dev (page, NULL, NULL);
 
   for (i = 0; i < out->getNumImages (); i++) {
     PopplerImageMapping *mapping;
@@ -1180,7 +1166,7 @@ poppler_page_get_image_mapping (PopplerPage *page)
 
     image->getRect (&(mapping->area.x1), &(mapping->area.y1),
 		    &(mapping->area.x2), &(mapping->area.y2));
-    mapping->image = poppler_page_image_pixbuf_create (page, image);
+    mapping->image_id = i;
     
     mapping->area.x1 -= page->page->getCropBox()->x1;
     mapping->area.x2 -= page->page->getCropBox()->x1;
@@ -1193,11 +1179,39 @@ poppler_page_get_image_mapping (PopplerPage *page)
   return map_list;	
 }
 
-static void
-poppler_images_mapping_free (PopplerImageMapping *mapping)
+static GBool
+image_draw_decide_cb (int image_id, void *data)
 {
-  g_object_unref (mapping->image);
-  g_free (mapping);
+  return (image_id == GPOINTER_TO_INT (data));
+}
+
+/**
+ * poppler_page_get_image:
+ * @page: A #PopplerPage
+ * @image_id: The image identificator
+ *
+ * Returns a cairo surface for the image of the @page
+ *
+ * Return value: A cairo surface for the image
+ **/
+cairo_surface_t *
+poppler_page_get_image (PopplerPage *page,
+			gint         image_id)
+{
+  CairoImageOutputDev *out;
+  cairo_surface_t *image;
+  
+  g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
+
+  out = poppler_page_get_image_output_dev (page,
+					   image_draw_decide_cb,
+					   GINT_TO_POINTER (image_id));
+
+  if (image_id >= out->getNumImages ())
+    return NULL;
+
+  image = out->getImage (image_id)->getImage ();
+  return image ? cairo_surface_reference (image) : NULL;
 }
 
 /**
@@ -1213,11 +1227,11 @@ poppler_page_free_image_mapping (GList *list)
   if (list == NULL)
     return;
 
-  g_list_foreach (list, (GFunc) (poppler_images_mapping_free), NULL);
+  g_list_foreach (list, (GFunc)g_free, NULL);
   g_list_free (list);
 }
 
-#else
+#else /* HAVE_CAIRO */
 
 GList *
 poppler_page_get_image_mapping (PopplerPage *page)
@@ -1593,8 +1607,6 @@ poppler_image_mapping_copy (PopplerImageMapping *mapping)
   new_mapping = poppler_image_mapping_new ();
 
   *new_mapping = *mapping;
-  if (new_mapping->image)
-    new_mapping->image = gdk_pixbuf_copy (new_mapping->image);
 
   return new_mapping;
 }
@@ -1602,9 +1614,6 @@ poppler_image_mapping_copy (PopplerImageMapping *mapping)
 void
 poppler_image_mapping_free (PopplerImageMapping *mapping)
 {
-  if (mapping->image)
-    g_object_unref (mapping->image);
-
   g_free (mapping);
 }
 
diff --git a/glib/poppler-page.h b/glib/poppler-page.h
index c2cc51d..f8de186 100644
--- a/glib/poppler-page.h
+++ b/glib/poppler-page.h
@@ -84,6 +84,10 @@ GList                 *poppler_page_get_link_mapping     (PopplerPage        *pa
 void                   poppler_page_free_link_mapping    (GList              *list);
 GList                 *poppler_page_get_image_mapping    (PopplerPage        *page);
 void                   poppler_page_free_image_mapping   (GList              *list);
+#ifdef POPPLER_HAS_CAIRO
+cairo_surface_t       *poppler_page_get_image            (PopplerPage        *page,
+							  gint                image_id);
+#endif
 GList              *poppler_page_get_form_field_mapping  (PopplerPage        *page);
 void                poppler_page_free_form_field_mapping (GList              *list);
 GdkRegion             *poppler_page_get_selection_region (PopplerPage        *page,
@@ -167,7 +171,7 @@ void                   poppler_page_transition_free     (PopplerPageTransition *
 struct  _PopplerImageMapping
 {
   PopplerRectangle area;
-  GdkPixbuf *image;	
+  gint image_id;	
 };
 
 GType                  poppler_image_mapping_get_type (void) G_GNUC_CONST;
diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index ef6e42f..99f5c2b 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -51,9 +51,8 @@ static inline void printMatrix(cairo_matrix_t *matrix){
 // CairoImage
 //------------------------------------------------------------------------
 
-CairoImage::CairoImage (cairo_surface_t *image,
-			double x1, double y1, double x2, double y2) {
-  this->image = cairo_surface_reference (image);
+CairoImage::CairoImage (double x1, double y1, double x2, double y2) {
+  this->image = NULL;
   this->x1 = x1;
   this->y1 = y1;
   this->x2 = x2;
@@ -65,6 +64,12 @@ CairoImage::~CairoImage () {
     cairo_surface_destroy (image);
 }
 
+void CairoImage::setImage (cairo_surface_t *image) {
+  if (this->image)
+    cairo_surface_destroy (this->image);
+  this->image = cairo_surface_reference (image);
+}
+
 //------------------------------------------------------------------------
 // CairoOutputDev
 //------------------------------------------------------------------------
@@ -1624,6 +1629,8 @@ CairoImageOutputDev::CairoImageOutputDev()
   images = NULL;
   numImages = 0;
   size = 0;
+  imgDrawCbk = NULL;
+  imgDrawCbkData = NULL;
 }
 
 CairoImageOutputDev::~CairoImageOutputDev()
@@ -1668,20 +1675,23 @@ void CairoImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *st
   x2 = x1 + width;
   y2 = y1 + height;
 
-  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
-  cr = cairo_create (surface);
-  setCairo (cr);
-  cairo_translate (cr, 0, height);
-  cairo_scale (cr, width, -height);
+  image = new CairoImage (x1, y1, x2, y2);
+  saveImage (image);
 
-  CairoOutputDev::drawImageMask(state, ref, str, width, height, invert, inlineImg);
+  if (imgDrawCbk && imgDrawCbk (numImages - 1, imgDrawCbkData)) {
+    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+    cr = cairo_create (surface);
+    setCairo (cr);
+    cairo_translate (cr, 0, height);
+    cairo_scale (cr, width, -height);
 
-  image = new CairoImage (surface, x1, y1, x2, y2);
-  saveImage (image);
-  
-  setCairo (NULL);
-  cairo_surface_destroy (surface);
-  cairo_destroy (cr);
+    CairoOutputDev::drawImageMask(state, ref, str, width, height, invert, inlineImg);
+    image->setImage (surface);
+
+    setCairo (NULL);
+    cairo_surface_destroy (surface);
+    cairo_destroy (cr);
+  }
 }
 
 void CairoImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
@@ -1708,20 +1718,23 @@ void CairoImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
   x2 = x1 + width;
   y2 = y1 + height;
 
-  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
-  cr = cairo_create (surface);
-  setCairo (cr);
-  cairo_translate (cr, 0, height);
-  cairo_scale (cr, width, -height);
-
-  CairoOutputDev::drawImage(state, ref, str, width, height, colorMap, maskColors, inlineImg);
-
-  image = new CairoImage (surface, x1, y1, x2, y2);
+  image = new CairoImage (x1, y1, x2, y2);
   saveImage (image);
-  
-  setCairo (NULL);
-  cairo_surface_destroy (surface);
-  cairo_destroy (cr);
+
+  if (imgDrawCbk && imgDrawCbk (numImages - 1, imgDrawCbkData)) {
+    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+    cr = cairo_create (surface);
+    setCairo (cr);
+    cairo_translate (cr, 0, height);
+    cairo_scale (cr, width, -height);
+    
+    CairoOutputDev::drawImage(state, ref, str, width, height, colorMap, maskColors, inlineImg);
+    image->setImage (surface);
+    
+    setCairo (NULL);
+    cairo_surface_destroy (surface);
+    cairo_destroy (cr);
+  }
 }
 
 void CairoImageOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str,
@@ -1751,21 +1764,24 @@ void CairoImageOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stre
   x2 = x1 + width;
   y2 = y1 + height;
 
-  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
-  cr = cairo_create (surface);
-  setCairo (cr);
-  cairo_translate (cr, 0, height);
-  cairo_scale (cr, width, -height);
-
-  CairoOutputDev::drawSoftMaskedImage(state, ref, str, width, height, colorMap,
-				      maskStr, maskWidth, maskHeight, maskColorMap);
-
-  image = new CairoImage (surface, x1, y1, x2, y2);
+  image = new CairoImage (x1, y1, x2, y2);
   saveImage (image);
-  
-  setCairo (NULL);
-  cairo_surface_destroy (surface);
-  cairo_destroy (cr);
+
+  if (imgDrawCbk && imgDrawCbk (numImages - 1, imgDrawCbkData)) {
+    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+    cr = cairo_create (surface);
+    setCairo (cr);
+    cairo_translate (cr, 0, height);
+    cairo_scale (cr, width, -height);
+    
+    CairoOutputDev::drawSoftMaskedImage(state, ref, str, width, height, colorMap,
+					maskStr, maskWidth, maskHeight, maskColorMap);
+    image->setImage (surface);
+    
+    setCairo (NULL);
+    cairo_surface_destroy (surface);
+    cairo_destroy (cr);
+  }
 }
 
 void CairoImageOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str,
@@ -1795,19 +1811,22 @@ void CairoImageOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *
   x2 = x1 + width;
   y2 = y1 + height;
 
-  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
-  cr = cairo_create (surface);
-  setCairo (cr);
-  cairo_translate (cr, 0, height);
-  cairo_scale (cr, width, -height);
-
-  CairoOutputDev::drawMaskedImage(state, ref, str, width, height, colorMap,
-				  maskStr, maskWidth, maskHeight, maskInvert);
-
-  image = new CairoImage (surface, x1, y1, x2, y2);
+  image = new CairoImage (x1, y1, x2, y2);
   saveImage (image);
-  
-  setCairo (NULL);
-  cairo_surface_destroy (surface);
-  cairo_destroy (cr);
+
+  if (imgDrawCbk && imgDrawCbk (numImages - 1, imgDrawCbkData)) {
+    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+    cr = cairo_create (surface);
+    setCairo (cr);
+    cairo_translate (cr, 0, height);
+    cairo_scale (cr, width, -height);
+    
+    CairoOutputDev::drawMaskedImage(state, ref, str, width, height, colorMap,
+				    maskStr, maskWidth, maskHeight, maskInvert);
+    image->setImage (surface);
+    
+    setCairo (NULL);
+    cairo_surface_destroy (surface);
+    cairo_destroy (cr);
+  }
 }
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index ade108e..ae44532 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -34,11 +34,14 @@ class CairoFont;
 class CairoImage {
 public:
   // Constructor.
-  CairoImage (cairo_surface_t *image, double x1, double y1, double x2, double y2);
+  CairoImage (double x1, double y1, double x2, double y2);
 
   // Destructor.
   ~CairoImage ();
 
+  // Set the image cairo surface
+  void setImage (cairo_surface_t *image);
+  
   // Get the image cairo surface
   cairo_surface_t *getImage () const { return image; }
 
@@ -324,16 +327,21 @@ public:
   virtual void clearSoftMask(GfxState * /*state*/) {}
 
   //----- Image list
+  // By default images are not rendred
+  void setImageDrawDecideCbk(GBool (*cbk)(int img_id, void *data),
+			     void *data) { imgDrawCbk = cbk; imgDrawCbkData = data; }
   // Iterate through list of images.
   int getNumImages() const { return numImages; }
   CairoImage *getImage(int i) const { return images[i]; }
 
 private:
   void saveImage(CairoImage *image);
-	  
+  
   CairoImage **images;
   int numImages;
   int size;
+  GBool (*imgDrawCbk)(int img_id, void *data);
+  void *imgDrawCbkData;
 };
 
 #endif


More information about the poppler mailing list