[giv] Major memory leak fixes and addition of multi line strings.



commit aee7c62e671a8a1e275db60c53e55a5409041b88
Author: Dov Grobgeld <dov grobgeld gmail com>
Date:   Wed May 16 22:43:52 2012 +0300

    Major memory leak fixes and addition of multi line strings.

 examples/text-unicode.giv |    8 ++++
 src/GivPainterAgg.cc      |    1 +
 src/GivRenderer.cc        |   30 +++++++++++++-
 src/giv-data.cc           |   14 ++++++-
 src/giv-data.h            |   10 +++++
 src/giv-parser.cc         |   97 ++++++++++++++++++++++++++++++++++++++++-----
 src/giv-win.gob           |   37 +++++++----------
 src/givimage.c            |    3 +-
 8 files changed, 164 insertions(+), 36 deletions(-)
---
diff --git a/examples/text-unicode.giv b/examples/text-unicode.giv
index ff8f295..aa8081b 100644
--- a/examples/text-unicode.giv
+++ b/examples/text-unicode.giv
@@ -24,3 +24,11 @@ $color red/80
 T5 100 50 <span size="xx-large">x<sup>2</sup>+y<sup>2</sup>=z<sub>2</sub></span>
 T5 100 20 <u><span color="red">R</span><span color="green">G</span><span color="blue">B</span></u>
 
+$pango_markup 
+$color green
+$scale_font 1
+$font sans
+$text_style shadow
+$shadow_color black/0.3
+$shadow_offset 1 1
+T5 100 200 Multi\nlines\nare\nnice.
diff --git a/src/GivPainterAgg.cc b/src/GivPainterAgg.cc
index 7f1a563..3144b1b 100644
--- a/src/GivPainterAgg.cc
+++ b/src/GivPainterAgg.cc
@@ -249,6 +249,7 @@ GivPainterAgg::add_text(const char *text,
         pango_layout_set_markup(d->layout, text, -1);
     else
         pango_layout_set_text (d->layout, text, -1);
+    pango_layout_set_alignment(d->layout, PangoAlignment((text_align-1)%3));
 
     pango_layout_get_extents(d->layout,
                              NULL,
diff --git a/src/GivRenderer.cc b/src/GivRenderer.cc
index 2775989..8669b90 100644
--- a/src/GivRenderer.cc
+++ b/src/GivRenderer.cc
@@ -219,11 +219,39 @@ void GivRenderer::paint()
             for (int p_idx=0; p_idx<(int)dataset->points->len; p_idx++) {
                 point_t p = g_array_index(dataset->points, point_t, p_idx);
 
-                if (p.op == OP_TEXT) {
+                if (p.op == OP_TEXT)
+                  {
                     double m_x = p.x * scale_x - shift_x;
                     double m_y = p.y * scale_y - shift_y;
                     const char *text = p.text_object->string;
                     int text_align = p.text_object->text_align;
+                    if (dataset->text_style == TEXT_STYLE_DROP_SHADOW)
+                      {
+                        double rr = cs*dataset->shadow_color.red;
+                        double gg = cs*dataset->shadow_color.green;
+                        double bb = cs*dataset->shadow_color.blue;
+                        double alpha = cs*dataset->shadow_color.alpha;
+
+                        double shift_x = dataset->shadow_offset_x;
+                        double shift_y = dataset->shadow_offset_y;
+                        if (dataset->do_scale_fonts)
+                          {
+                            shift_x *= scale_x;
+                            shift_y *= scale_y;
+                          }
+                        painter.set_color(rr,gg,bb,alpha);
+                        painter.add_text(text,
+                                         m_x+shift_x,
+                                         m_y+shift_y,
+                                         text_align,
+                                         dataset->do_pango_markup);
+                        // Reset color
+                        rr = cs*dataset->color.red;
+                        gg = cs*dataset->color.green;
+                        bb = cs*dataset->color.blue;
+                        alpha = cs*dataset->color.alpha;
+                        painter.set_color(rr,gg,bb,alpha);
+                      }
                     painter.add_text(text, m_x, m_y, text_align, dataset->do_pango_markup);
                 }
             }
diff --git a/src/giv-data.cc b/src/giv-data.cc
index f3f64e5..d3fcb2b 100644
--- a/src/giv-data.cc
+++ b/src/giv-data.cc
@@ -48,7 +48,12 @@ giv_dataset_t *new_giv_dataset(int num_datasets)
     dataset_p->font_name = NULL;
     dataset_p->file_name = NULL;
     dataset_p->color = color_of_black; 
+    dataset_p->shadow_color = color_of_black;
+    dataset_p->shadow_offset_x = 0.5; 
+    dataset_p->shadow_offset_y = 0.5;
+    dataset_p->text_style = TEXT_STYLE_NORMAL;
     dataset_p->outline_color = color_of_black;
+    dataset_p->outline_color.alpha = 128*256;
     dataset_p->quiver_color = color_of_black;
     dataset_p->quiver_scale = 1.0;
 #if 0
@@ -70,12 +75,17 @@ void free_giv_data_set(giv_dataset_t *dataset_p)
     g_free(dataset_p->path_name);
     if (dataset_p->set_name)
         g_free(dataset_p->set_name);
-    g_array_free(dataset_p->points, TRUE);
     if (dataset_p->file_name)
         g_free(dataset_p->file_name);
     if (dataset_p->balloon_string)
         g_string_free(dataset_p->balloon_string, TRUE);
-    
+    for (int i=0; i<(int)dataset_p->points->len; i++)
+        {
+          point_t p = g_array_index(dataset_p->points, point_t, i);
+          if (p.op == OP_TEXT)
+            g_free(p.text_object->string);
+        }
+    g_array_free(dataset_p->points, TRUE);
     g_free(dataset_p);
 }
 
diff --git a/src/giv-data.h b/src/giv-data.h
index c91b0e9..c7a1e36 100644
--- a/src/giv-data.h
+++ b/src/giv-data.h
@@ -38,6 +38,12 @@ enum GivArrowType
     ARROW_TYPE_BOTH = 3,
 };
 
+enum GivTextStyle
+{
+  TEXT_STYLE_NORMAL,
+  TEXT_STYLE_DROP_SHADOW
+};
+
 typedef struct {
     guint16 red;
     guint16 green;
@@ -50,6 +56,7 @@ typedef struct
     GivColor color;
     GivColor outline_color;
     GivColor quiver_color;
+    GivColor shadow_color;
     gdouble line_width;
     gdouble quiver_scale;
     gint line_style;
@@ -57,6 +64,7 @@ typedef struct
     gdouble text_size;
     gboolean do_scale_fonts;
     gboolean do_pango_markup;
+    enum GivTextStyle text_style;
     gint num_dashes;
     gdouble mark_size;
     gboolean do_scale_marks;
@@ -75,6 +83,8 @@ typedef struct
     GString *balloon_string;
     char *font_name;
     gdouble *dashes;
+    gdouble shadow_offset_x;
+    gdouble shadow_offset_y;
 } giv_dataset_t;
 
 typedef struct
diff --git a/src/giv-parser.cc b/src/giv-parser.cc
index 5ee9e9d..5f0f6bb 100644
--- a/src/giv-parser.cc
+++ b/src/giv-parser.cc
@@ -27,6 +27,8 @@ enum
   STRING_CHANGE_COLOR,
   STRING_CHANGE_OUTLINE_COLOR,
   STRING_CHANGE_QUIVER_COLOR,
+  STRING_CHANGE_SHADOW_COLOR,
+  STRING_CHANGE_SHADOW_OFFSET,
   STRING_CHANGE_QUIVER_SCALE,
   STRING_CHANGE_LINE_WIDTH,
   STRING_CHANGE_MARKS,
@@ -56,7 +58,8 @@ enum
   STRING_STYLE,
   STRING_DEF_STYLE,
   STRING_HIDE,
-  STRING_IGNORE
+  STRING_IGNORE,
+  STRING_TEXT_STYLE
 };
 
 #define COLOR_NONE 0xfffe
@@ -304,8 +307,8 @@ string_strdup_word (const char *string, int idx)
   return word;
 }
 
-char *
-string_strdup_rest (const char *string, int idx)
+static char *
+string_strdup_rest (const char *string, int idx, bool parse_escape)
 {
   const char *p = string;
   int in_word = 0;
@@ -317,10 +320,12 @@ string_strdup_rest (const char *string, int idx)
   /* printf("p = 0x%x\n", p); */
   while (*p)
     {
+      char ch = *p;
+
       /* printf("%c\n", *p); fflush(stdout); */
       if (!in_word)
 	{
-	  if (*p != ' ' && *p != '\n' && *p != '\t')
+	  if (ch != ' ' && ch != '\n' && ch != '\t')
 	    {
 	      in_word = 1;
 	      word_count++;
@@ -330,7 +335,7 @@ string_strdup_rest (const char *string, int idx)
 	}
       else if (in_word)
 	{
-	  if (*p == ' ' || *p == '\n' || *p == '\t')
+	  if (ch == ' ' || ch == '\n' || ch == '\t')
 	    {
 	      if (idx == word_count)
 		break;
@@ -347,6 +352,36 @@ string_strdup_rest (const char *string, int idx)
       word = g_new (char, nchr + 1);
       strncpy (word, word_start, nchr);
       word[nchr] = 0;
+      if (parse_escape)
+        {
+          gchar *word_copy = g_strdup(word);
+          char *p = word_copy;
+          char *pd = word;
+          while(*p)
+            {
+              char ch = *p;
+              if (ch == '\\')
+                {
+                  p++;
+                  if (!*p)
+                    break;
+                  if (*p=='n')
+                    ch = '\n';
+                  else if (*p == '\\')
+                    ch = '\\';
+                  else
+                    {
+                      // ignore the escape character
+                      ch = '\\';
+                      p--;
+                    }
+                }
+              *pd++ = ch;
+              p++;
+            }
+          *pd=0;
+          g_free(word_copy);
+        }
     }
   return word;
 }
@@ -414,6 +449,14 @@ parse_string (const char *string, const char *fn, gint linenum)
       {
 	type = STRING_CHANGE_QUIVER_COLOR;
       }
+      NCASE ("$shadow_color")
+      {
+	type = STRING_CHANGE_SHADOW_COLOR;
+      }
+      NCASE ("$shadow_offset")
+      {
+	type = STRING_CHANGE_SHADOW_OFFSET;
+      }
       NCASE ("$quiver_scale")
       {
 	type = STRING_CHANGE_QUIVER_SCALE;
@@ -454,6 +497,10 @@ parse_string (const char *string, const char *fn, gint linenum)
       {
           type = STRING_FONT;
       }
+      NCASE ("$text_style")
+      {
+          type = STRING_TEXT_STYLE;
+      }
       NCASE ("$nomark")
       {
 	type = STRING_CHANGE_NO_MARK;
@@ -647,7 +694,7 @@ giv_parser_giv_marks_data_add_line(GivParser *gp,
             tm->text_align = 1;
             if (S_[1] >= '0' && S_[1] <= '9') 
                 tm->text_align = atoi(&S_[1]);
-            tm->string = string_strdup_rest(S_, 3);
+            tm->string = string_strdup_rest(S_, 3, TRUE);
             p.op = OP_TEXT;
             p.text_object = tm;
             g_array_append_val(marks->points, p);
@@ -658,7 +705,7 @@ giv_parser_giv_marks_data_add_line(GivParser *gp,
         break;
     case STRING_BALLOON:
         {
-            char *s = string_strdup_rest(S_,1);
+            char *s = string_strdup_rest(S_,1,TRUE);
             if (!marks->balloon_string)
                 marks->balloon_string = g_string_new(s);
             else {
@@ -769,7 +816,7 @@ giv_parser_giv_marks_data_add_line(GivParser *gp,
     case STRING_FONT:
         if (marks->font_name)
             g_free(marks->font_name);
-        marks->font_name = string_strdup_rest(S_, 1);
+        marks->font_name = string_strdup_rest(S_, 1, TRUE);
         break;
     case STRING_CHANGE_COLOR:
         {
@@ -811,6 +858,28 @@ giv_parser_giv_marks_data_add_line(GivParser *gp,
             g_free(color_name);
             break;
         }
+    case STRING_CHANGE_SHADOW_COLOR:
+        {
+            char *color_name = string_strdup_word(S_, 1);
+            GivColor color = {0,0,0,0};
+            if ((slip)color_name == "none")
+                marks->shadow_color.alpha = COLOR_NONE;
+            else {
+                if (color_parse(color_name,&color))
+                    marks->shadow_color = color;
+            }
+            g_free(color_name);
+            break;
+        }
+    case STRING_CHANGE_SHADOW_OFFSET:
+        {
+            char *arg1 = string_strdup_word(S_, 1);
+            char *arg2 = string_strdup_word(S_, 2);
+            marks->shadow_offset_x = atof(arg1);
+            marks->shadow_offset_y = atof(arg2);
+            g_free(arg1);
+            g_free(arg2);
+        }
     case STRING_CHANGE_QUIVER_SCALE:
         marks->quiver_scale = string_to_atof(S_, 1);
 
@@ -848,12 +917,12 @@ giv_parser_giv_marks_data_add_line(GivParser *gp,
     case STRING_PATH_NAME:
         if (marks->path_name)
             g_free(marks->path_name);
-        marks->path_name = string_strdup_rest(S_, 1);
+        marks->path_name = string_strdup_rest(S_, 1,FALSE);
         break;
     case STRING_DEF_STYLE:
         {
             char *style_name = string_strdup_word(S_, 1);
-            char *style_string = string_strdup_rest(S_, 2);
+            char *style_string = string_strdup_rest(S_, 2,FALSE);
             giv_parser_giv_style_add_string(gp, style_name, style_string);
             g_free(style_name);
             g_free(style_string);
@@ -871,6 +940,14 @@ giv_parser_giv_marks_data_add_line(GivParser *gp,
             marks->is_visible = false;
             break;
         }
+    case STRING_TEXT_STYLE:
+        {
+          char *text_style = string_strdup_word(S_,1);
+          if (strcmp(text_style, "shadow") == 0)
+            marks->text_style = TEXT_STYLE_DROP_SHADOW;
+          g_free(text_style);
+          break;
+        }
     default:
         ;
 #if 0
diff --git a/src/giv-win.gob b/src/giv-win.gob
index 27c5c1e..651171f 100644
--- a/src/giv-win.gob
+++ b/src/giv-win.gob
@@ -460,22 +460,16 @@ class Giv:Win from Gtk:Window
         destroy {
         if (img_org) {
             giv_image_unref(img_org);
+            img_org = NULL;
         }
     };
     private double contrast_min = -1;
     private double contrast_max = -1;
     private gchar *format = NULL destroy { g_free(format); };
-//    private GdkPixbuf *img_org = NULL
-//        destroy {
-//            if (img_org) {
-//                g_object_unref(img_org);
-//            };
-//        };
     private GdkPixbuf *img_display = NULL
         destroy {
-            if (img_display) {
-                g_object_unref(img_display);
-            };
+            if (img_display) 
+              g_object_unref(img_display);
         };
         
     // This image is a copy of the img display but with label
@@ -1051,7 +1045,7 @@ class Giv:Win from Gtk:Window
     {
         num_top_levels--;
         gtk_widget_destroy(GTK_WIDGET(self));
-        
+
         if (num_top_levels == 0)
             gtk_main_quit();
     }
@@ -1118,13 +1112,12 @@ class Giv:Win from Gtk:Window
         selfp->auto_reload_trigger = false;
         
         if (selfp->img_org)
+          {
             giv_image_unref(selfp->img_org);
-        if (selfp->img_display) {
-            g_object_unref(selfp->img_display);
-            selfp->img_display = NULL;
-        }
-
+            selfp->img_org = NULL;
+          }
         selfp->img_org = new_img;
+
         if (selfp->do_auto_contrast)
             giv_image_get_min_max(new_img,
                                   // output
@@ -1272,10 +1265,11 @@ class Giv:Win from Gtk:Window
         // If the new entry does not contain an image, then clear
         // the old image.
         if (!has_image) {
-            if (selfp->img_org) {
+            if (selfp->img_org)
+              {
                 giv_image_unref(selfp->img_org);
                 selfp->img_org = NULL;
-            }
+              }
             if (selfp->img_display) {
                 g_object_unref(selfp->img_display);
                 selfp->img_display = NULL;
@@ -1419,9 +1413,10 @@ class Giv:Win from Gtk:Window
                           GivImage *image)
     {
         if (selfp->img_org)
+          {
             giv_image_unref(selfp->img_org);
-        if (selfp->img_display)
-            g_object_ref(selfp->img_display);
+            selfp->img_org = NULL;
+          }
         selfp->img_org = image;
         apply_color_map(self);
         gtk_image_viewer_set_image(GTK_IMAGE_VIEWER(selfp->w_imgv),
@@ -1874,7 +1869,6 @@ cb_key_press_event (GtkWidget * widget,
               selfp->current_slice = 0;
 
           // Redraw the image
-          giv_image_ref(selfp->img_org);
           giv_win_set_image(GIV_WIN(self),
                             selfp->img_org);
           giv_win_set_image_info(GIV_WIN(self));
@@ -3264,9 +3258,8 @@ apply_color_map(GivWin *self)
     GdkPixbuf *org_pixbuf = giv_image_get_pixbuf(selfp->img_org,
                                                  selfp->current_slice,
                                                  min, max);
-    
     if (selfp->img_display)
-        g_object_unref(selfp->img_display);
+      g_object_unref(selfp->img_display);
 
     const guint8 *tmap = NULL;
     if (selfp->colormap == PSEUDO_COLOR_OFF
diff --git a/src/givimage.c b/src/givimage.c
index d355788..d21cb88 100644
--- a/src/givimage.c
+++ b/src/givimage.c
@@ -161,7 +161,7 @@ GivImage *giv_image_new_from_file(const char *filename,
                    gdk_pixbuf_get_pixels(pixbuf),
                    row_stride * height);
         }
-        gdk_pixbuf_unref(pixbuf);
+        g_object_unref(pixbuf);
     }
     // Space separated value. A simple text format parser. Still
     // doesn't support comments. Fix this!
@@ -335,6 +335,7 @@ void giv_image_unref(GivImage *img)
 
     if (img->ref_count !=0)
         return;
+    g_free(img->buf.buf);
     g_hash_table_unref(img->attribute_map);
     g_free(img);
 }



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