[dia] Fix (inlined) image related leaks



commit c0a2ad1cb354f7c25d691d74882765e9b6671e9d
Author: Hans Breuer <hans breuer org>
Date:   Thu Jan 2 13:28:19 2014 +0100

    Fix (inlined) image related leaks
    
     - DiaImage::scaled was leaked
     - undo information of dia_object_set_pixbuf() was not freed completely
     - Standard - Image (_Image::pixbuf) was not properly reference counted

 app/commands.c              |    4 +++-
 lib/dia_image.c             |    5 +++++
 lib/prop_pixbuf.c           |    2 ++
 objects/standard/image.c    |   23 ++++++++++++++++-------
 plug-ins/pdf/pdf-import.cpp |   27 ++++++++++++++++++---------
 5 files changed, 44 insertions(+), 17 deletions(-)
---
diff --git a/app/commands.c b/app/commands.c
index 811aa71..99f2994 100644
--- a/app/commands.c
+++ b/app/commands.c
@@ -283,8 +283,10 @@ received_clipboard_image_handler(GtkClipboard *clipboard,
                                             &handle1, &handle2)) != NULL)) {
       /* as above, transfer the data */
       change = dia_object_set_pixbuf (obj, pixbuf);
-      if (change) /* ... but drop undo info */
+      if (change) { /* ... but drop undo info */
        change->free (change);
+       g_free (change);
+      }
       /* allow undo of the whole thing */
       undo_insert_objects(dia, g_list_prepend(NULL, obj), 1); 
 
diff --git a/lib/dia_image.c b/lib/dia_image.c
index 6bbb9a4..88598be 100644
--- a/lib/dia_image.c
+++ b/lib/dia_image.c
@@ -119,6 +119,11 @@ static void
 dia_image_finalize(GObject* object)
 {
   DiaImage *image = DIA_IMAGE(object);
+#ifdef SCALING_CACHE
+  if (image->scaled)
+    g_object_unref (image->scaled);
+  image->scaled = NULL;
+#endif
   if (image->image)
     g_object_unref (image->image);
   image->image = NULL;
diff --git a/lib/prop_pixbuf.c b/lib/prop_pixbuf.c
index 2402365..5a5e588 100644
--- a/lib/prop_pixbuf.c
+++ b/lib/prop_pixbuf.c
@@ -249,6 +249,8 @@ pixbufprop_set_from_offset(PixbufProperty *prop,
                            void *base, guint offset, guint offset2)
 {
   GdkPixbuf *dest = struct_member(base,offset,GdkPixbuf *);
+  if (dest == prop->pixbuf)
+    return;
   if (dest)
     g_object_unref (dest);
   if (prop->pixbuf)
diff --git a/objects/standard/image.c b/objects/standard/image.c
index 715e919..a2d1851 100644
--- a/objects/standard/image.c
+++ b/objects/standard/image.c
@@ -66,7 +66,7 @@ struct _Image {
   gchar *file;
   
   gboolean inline_data;
-  /* may contain the images pixbuf pointer */
+  /* may contain the images pixbuf pointer - if so: reference counted! */
   GdkPixbuf *pixbuf;
 
   gboolean draw_border;
@@ -184,8 +184,10 @@ static PropOffset image_offsets[] = {
 static void
 image_get_props(Image *image, GPtrArray *props)
 {
-  if (image->inline_data)
-    image->pixbuf = (GdkPixbuf *)dia_image_pixbuf (image->image);
+  if (image->inline_data) {
+    if (image->pixbuf != dia_image_pixbuf (image->image))
+      image->pixbuf = (GdkPixbuf *)g_object_ref (dia_image_pixbuf (image->image));
+  }
   object_get_props_from_offsets(&image->element.object, image_offsets, props);
 }
 
@@ -210,7 +212,9 @@ image_set_props(Image *image, GPtrArray *props)
       if (image->image)
         g_object_unref (image->image);
       image->image = dia_image_new_from_pixbuf (image->pixbuf ? image->pixbuf : pixbuf);
-      image->pixbuf = (GdkPixbuf *)dia_image_pixbuf (image->image);
+      if (image->pixbuf)
+        g_object_unref (image->pixbuf);
+      image->pixbuf = (GdkPixbuf *)g_object_ref (dia_image_pixbuf (image->image));
       if (pixbuf)
        g_object_unref (pixbuf);
     } else {
@@ -241,6 +245,7 @@ image_set_props(Image *image, GPtrArray *props)
       image->image = dia_image_get_broken();
     elem->height = (elem->width*(float)dia_image_height(image->image))/
       (float)dia_image_width(image->image);
+    /* release image->pixbuf? */
   }
   g_free(old_file);
   /* remember it */
@@ -526,13 +531,17 @@ image_create(Point *startpoint,
 }
 
 static void 
-image_destroy(Image *image) {
+image_destroy(Image *image)
+{
   if (image->file != NULL)
     g_free(image->file);
 
   if (image->image != NULL)
     dia_image_unref(image->image);
 
+  if (image->pixbuf != NULL)
+    g_object_unref(image->pixbuf);
+
   element_destroy(&image->element);
 }
 
@@ -574,9 +583,9 @@ image_copy(Image *image)
    * for every single undoable step */
   newimage->inline_data = image->inline_data;
   if (image->pixbuf)
-    newimage->pixbuf = g_object_ref(image->pixbuf);
+    newimage->pixbuf = g_object_ref (dia_image_pixbuf(newimage->image));
   else
-    newimage->pixbuf = image->pixbuf;
+    newimage->pixbuf = image->pixbuf; /* Just say NULL */
 
   newimage->mtime = image->mtime;
   newimage->draw_border = image->draw_border;
diff --git a/plug-ins/pdf/pdf-import.cpp b/plug-ins/pdf/pdf-import.cpp
index e13a361..d8ca7d2 100644
--- a/plug-ins/pdf/pdf-import.cpp
+++ b/plug-ins/pdf/pdf-import.cpp
@@ -569,6 +569,7 @@ DiaOutputDev::applyStyle (DiaObject *obj, bool fill)
 {
   GPtrArray *plist = g_ptr_array_new ();
 
+
   if (!fill) {
     prop_list_add_line_width (plist, this->line_width);
     prop_list_add_line_style (plist, this->line_style, this->dash_length);
@@ -603,7 +604,7 @@ DiaOutputDev::stroke (GfxState *state)
   GfxPath *path = state->getPath();
   bool haveClose = false;
 
-  if (doPath (points, state, path, haveClose)) {
+  if (doPath (points, state, path, haveClose) && points->len > 1) {
     if (path->getNumSubpaths() == 1) {
       if (!haveClose)
         obj = create_standard_bezierline (points->len, &g_array_index (points, BezPoint, 0), NULL, NULL);
@@ -628,18 +629,24 @@ DiaOutputDev::_fill (GfxState *state, bool winding)
   GfxPath *path = state->getPath();
   bool haveClose = true;
 
-  if (doPath (points, state, path, haveClose)) {
+  if (doPath (points, state, path, haveClose) && points->len > 2) {
     if (path->getNumSubpaths() == 1 && haveClose)
       obj = create_standard_beziergon (points->len, &g_array_index (points, BezPoint, 0));
     else
       obj = create_standard_path (points->len, &g_array_index (points, BezPoint, 0));
     applyStyle (obj, true);
-    if (this->pattern)
-      dia_object_set_pattern (obj, this->pattern);
+    if (this->pattern) {
+      ObjectChange *change = dia_object_set_pattern (obj, this->pattern);
+      if (change) {
+       change->free (change);
+       g_free (change);
+      }
+    }
   }
   g_array_free (points, TRUE);
   if (obj) {
-    dia_object_set_meta (obj, "fill-rule", winding ? "winding" : "even-odd");
+    // Useful for debugging but high performance penalty 
+    // dia_object_set_meta (obj, "fill-rule", winding ? "winding" : "even-odd");
     addObject (obj);
   }
 }
@@ -788,10 +795,12 @@ DiaOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
   obj = create_standard_image (pos.x, pos.y, 
                               ctm[0]  * scale,
                               ctm[3]  * scale, NULL);
-  if ((change = dia_object_set_pixbuf (obj, pixbuf)) != NULL)
-    change->free (change); /* reference transfered */
-  else
-    g_object_unref (pixbuf);
+  if ((change = dia_object_set_pixbuf (obj, pixbuf)) != NULL) {
+    change->free (change);
+    g_free (change);
+  }
+
+  g_object_unref (pixbuf);
 
   addObject (obj);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]