Make save IO graph work, I had to make a local copy of
authoretxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 14 Aug 2011 21:40:25 +0000 (21:40 +0000)
committeretxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 14 Aug 2011 21:40:25 +0000 (21:40 +0000)
GTK 3.0 function gdk_pixbuf_get_from_surface() put in gui_util.c

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@38541 f5534014-38df-0310-8fa8-9805f1628bb7

gtk/gui_utils.c
gtk/gui_utils.h
gtk/io_stat.c
gtk/pixmap_save.c
gtk/pixmap_save.h

index 7a9cdcf27695508d513745ce4d110b84180e361b..d6c21e4a214e459cfad6ae7ea688bc10f046c762 100644 (file)
@@ -1697,3 +1697,184 @@ ws_combo_box_set_active_iter(GtkComboBox *combo_box, GtkTreeIter *iter)
 {
     gtk_combo_box_set_active_iter(combo_box, iter);
 }
+
+
+/* Copy functions from GTK 3.0 to be used if GTK version is 2.22 or 2.24 to be able save Graphs to file */
+#if GTK_CHECK_VERSION(2,22,0)
+#if !GTK_CHECK_VERSION(3,0,0)
+static cairo_format_t
+gdk_cairo_format_for_content (cairo_content_t content)
+{
+  switch (content)
+    {
+    case CAIRO_CONTENT_COLOR:
+      return CAIRO_FORMAT_RGB24;
+    case CAIRO_CONTENT_ALPHA:
+      return CAIRO_FORMAT_A8;
+    case CAIRO_CONTENT_COLOR_ALPHA:
+    default:
+      return CAIRO_FORMAT_ARGB32;
+    }
+}
+
+static cairo_surface_t *
+gdk_cairo_surface_coerce_to_image (cairo_surface_t *surface,
+                                   cairo_content_t  content,
+                                   int              src_x,
+                                   int              src_y,
+                                   int              width,
+                                   int              height)
+{
+  cairo_surface_t *copy;
+  cairo_t *cr;
+
+  copy = cairo_image_surface_create (gdk_cairo_format_for_content (content),
+                                     width,
+                                     height);
+
+  cr = cairo_create (copy);
+  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+  cairo_set_source_surface (cr, surface, -src_x, -src_y);
+  cairo_paint (cr);
+  cairo_destroy (cr);
+
+  return copy;
+}
+
+static void
+convert_alpha (guchar *dest_data,
+               int     dest_stride,
+               guchar *src_data,
+               int     src_stride,
+               int     src_x,
+               int     src_y,
+               int     width,
+               int     height)
+{
+  int x, y;
+
+  src_data += src_stride * src_y + src_x * 4;
+
+  for (y = 0; y < height; y++) {
+    guint32 *src = (guint32 *) src_data;
+
+    for (x = 0; x < width; x++) {
+      guint alpha = src[x] >> 24;
+
+      if (alpha == 0)
+        {
+          dest_data[x * 4 + 0] = 0;
+          dest_data[x * 4 + 1] = 0;
+          dest_data[x * 4 + 2] = 0;
+        }
+      else
+        {
+          dest_data[x * 4 + 0] = (((src[x] & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
+          dest_data[x * 4 + 1] = (((src[x] & 0x00ff00) >>  8) * 255 + alpha / 2) / alpha;
+          dest_data[x * 4 + 2] = (((src[x] & 0x0000ff) >>  0) * 255 + alpha / 2) / alpha;
+        }
+      dest_data[x * 4 + 3] = alpha;
+    }
+
+    src_data += src_stride;
+    dest_data += dest_stride;
+  }
+}
+
+static void
+convert_no_alpha (guchar *dest_data,
+                  int     dest_stride,
+                  guchar *src_data,
+                  int     src_stride,
+                  int     src_x,
+                  int     src_y,
+                  int     width,
+                  int     height)
+{
+  int x, y;
+
+  src_data += src_stride * src_y + src_x * 4;
+
+  for (y = 0; y < height; y++) {
+    guint32 *src = (guint32 *) src_data;
+
+    for (x = 0; x < width; x++) {
+      dest_data[x * 3 + 0] = src[x] >> 16;
+      dest_data[x * 3 + 1] = src[x] >>  8;
+      dest_data[x * 3 + 2] = src[x];
+    }
+
+    src_data += src_stride;
+    dest_data += dest_stride;
+  }
+}
+
+/**
+ * gdk_pixbuf_get_from_surface:
+ * @surface: surface to copy from
+ * @src_x: Source X coordinate within @surface
+ * @src_y: Source Y coordinate within @surface
+ * @width: Width in pixels of region to get
+ * @height: Height in pixels of region to get
+ *
+ * Transfers image data from a #cairo_surface_t and converts it to an RGB(A)
+ * representation inside a #GdkPixbuf. This allows you to efficiently read
+ * individual pixels from cairo surfaces. For #GdkWindows, use
+ * gdk_pixbuf_get_from_window() instead.
+ *
+ * This function will create an RGB pixbuf with 8 bits per channel.
+ * The pixbuf will contain an alpha channel if the @surface contains one.
+ *
+ * Return value: (transfer full): A newly-created pixbuf with a reference
+ *     count of 1, or %NULL on error
+ */
+GdkPixbuf *
+gdk_pixbuf_get_from_surface  (cairo_surface_t *surface,
+                              gint             src_x,
+                              gint             src_y,
+                              gint             width,
+                              gint             height)
+{
+  cairo_content_t content;
+  GdkPixbuf *dest;
+
+  /* General sanity checks */
+  g_return_val_if_fail (surface != NULL, NULL);
+  g_return_val_if_fail (width > 0 && height > 0, NULL);
+
+  content = cairo_surface_get_content (surface) | CAIRO_CONTENT_COLOR;
+  dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+                         !!(content & CAIRO_CONTENT_ALPHA),
+                         8,
+                         width, height);
+
+  surface = gdk_cairo_surface_coerce_to_image (surface, content,
+                                               src_x, src_y,
+                                               width, height);
+  cairo_surface_flush (surface);
+  if (cairo_surface_status (surface) || dest == NULL)
+    {
+      cairo_surface_destroy (surface);
+      return NULL;
+    }
+
+  if (gdk_pixbuf_get_has_alpha (dest))
+    convert_alpha (gdk_pixbuf_get_pixels (dest),
+                   gdk_pixbuf_get_rowstride (dest),
+                   cairo_image_surface_get_data (surface),
+                   cairo_image_surface_get_stride (surface),
+                   0, 0,
+                   width, height);
+  else
+    convert_no_alpha (gdk_pixbuf_get_pixels (dest),
+                      gdk_pixbuf_get_rowstride (dest),
+                      cairo_image_surface_get_data (surface),
+                      cairo_image_surface_get_stride (surface),
+                      0, 0,
+                      width, height);
+
+  cairo_surface_destroy (surface);
+  return dest;
+}
+#endif /* !GTK_CHECK_VERSION(3,0,0) */
+#endif /* GTK_CHECK_VERSION(2,22,0) */
\ No newline at end of file
index 5e24f646ae63d4418a6059983674af9ea27d3d08..ffe6cf419752930bde2e66b944364a6dfff15f7c 100644 (file)
@@ -526,4 +526,13 @@ void ws_combo_box_set_active(GtkComboBox *combo_box, gint idx);
 void
 ws_combo_box_set_active_iter(GtkComboBox *combo_box, GtkTreeIter *iter);
 
+#if GTK_CHECK_VERSION(2,22,0)
+#if !GTK_CHECK_VERSION(3,0,0)
+GdkPixbuf *gdk_pixbuf_get_from_surface (cairo_surface_t *surface,
+                                        gint             src_x,
+                                        gint             src_y,
+                                        gint             width,
+                                        gint             height);
+#endif
+#endif
 #endif /* __GUI_UTIL__H__ */
index b325af5ac4cd72463314a8edd3febd7bb94d4026..4813162ae249b3e5ab265d956fd2b63631294be6 100644 (file)
@@ -175,8 +175,8 @@ typedef struct _io_stat_t {
        GtkWidget *scrollbar;
        guint first_frame_num[NUM_IO_ITEMS];
        guint last_frame_num;
-       int surface_width;
-       int surface_height;
+       int pixmap_width;
+       int pixmap_height;
        int pixels_per_tick;
        int max_y_units;
        int count_type;
@@ -854,8 +854,8 @@ io_stat_draw(io_stat_t *io)
        /*
         * Calculate the size of the drawing area for the actual plot
         */
-       draw_width=io->surface_width-io->right_x_border-io->left_x_border;
-       draw_height=io->surface_height-top_y_border-bottom_y_border;
+       draw_width=io->pixmap_width-io->right_x_border-io->left_x_border;
+       draw_height=io->pixmap_height-top_y_border-bottom_y_border;
 
 
        /*
@@ -870,7 +870,7 @@ io_stat_draw(io_stat_t *io)
 #else
                cr = gdk_cairo_create (io->pixmap);
 #endif
-               cairo_move_to (cr, 5, io->surface_height-bottom_y_border-draw_height-label_height/2);
+               cairo_move_to (cr, 5, io->pixmap_height-bottom_y_border-draw_height-label_height/2);
                pango_cairo_show_layout (cr, layout);
                cairo_destroy (cr);
                cr = NULL;
@@ -886,8 +886,8 @@ io_stat_draw(io_stat_t *io)
        cr = gdk_cairo_create (io->pixmap);
 #endif
        cairo_set_line_width (cr, 1.0);
-       cairo_move_to(cr, io->surface_width-io->right_x_border+1.5, top_y_border+0.5);
-       cairo_line_to(cr, io->surface_width-io->right_x_border+1.5, io->surface_height-bottom_y_border+0.5);
+       cairo_move_to(cr, io->pixmap_width-io->right_x_border+1.5, top_y_border+0.5);
+       cairo_line_to(cr, io->pixmap_width-io->right_x_border+1.5, io->pixmap_height-bottom_y_border+0.5);
        cairo_stroke(cr);
        cairo_destroy(cr);
        if(io->max_y_units==LOGARITHMIC_YSCALE){
@@ -906,15 +906,15 @@ io_stat_draw(io_stat_t *io)
                if(io->max_y_units==LOGARITHMIC_YSCALE){
                        if(i==ys) {
                                /* position for the 0 value */
-                               ypos=io->surface_height-bottom_y_border;
+                               ypos=io->pixmap_height-bottom_y_border;
                        } else if(i==tics) {
                                /* position for the top value, do not draw logarithmic tics above graph */
-                               ypos=io->surface_height-bottom_y_border-draw_height;
+                               ypos=io->pixmap_height-bottom_y_border-draw_height;
                        } else {
                                int j;
                                /* draw the logarithmic tics */
                                for(j=2;j<10;j++) {
-                                       ypos=(int)(io->surface_height-bottom_y_border-(draw_height-ystart)*(i+log10((double)j))/tics-ystart);
+                                       ypos=(int)(io->pixmap_height-bottom_y_border-(draw_height-ystart)*(i+log10((double)j))/tics-ystart);
                                        /* draw the tick */
 #if GTK_CHECK_VERSION(2,22,0)
                                        cr = cairo_create (io->surface);
@@ -922,12 +922,12 @@ io_stat_draw(io_stat_t *io)
                                        cr = gdk_cairo_create (io->pixmap);
 #endif
                                        cairo_set_line_width (cr, 1.0);
-                                       cairo_move_to(cr, io->surface_width-io->right_x_border+1.5, ypos+0.5);
-                                       cairo_line_to(cr, io->surface_width-io->right_x_border+1.5+xwidth,ypos+0.5);
+                                       cairo_move_to(cr, io->pixmap_width-io->right_x_border+1.5, ypos+0.5);
+                                       cairo_line_to(cr, io->pixmap_width-io->right_x_border+1.5+xwidth,ypos+0.5);
                                        cairo_stroke(cr);
                                        cairo_destroy(cr);
                                }
-                               ypos=io->surface_height-bottom_y_border-(draw_height-ystart)*i/tics-ystart;
+                               ypos=io->pixmap_height-bottom_y_border-(draw_height-ystart)*i/tics-ystart;
                        }
                        /* all "main" logarithmic lines are slightly longer */
                        xwidth=10;
@@ -936,7 +936,7 @@ io_stat_draw(io_stat_t *io)
                                /* first, middle and last tick are slightly longer */
                                xwidth=10;
                        }
-                       ypos=io->surface_height-bottom_y_border-draw_height*i/10;
+                       ypos=io->pixmap_height-bottom_y_border-draw_height*i/10;
                }
                /* draw the tick */
 #if GTK_CHECK_VERSION(2,22,0)
@@ -945,8 +945,8 @@ io_stat_draw(io_stat_t *io)
                cr = gdk_cairo_create (io->pixmap);
 #endif
                cairo_set_line_width (cr, 1.0);
-               cairo_move_to(cr, io->surface_width-io->right_x_border+1.5, ypos+0.5);
-               cairo_line_to(cr, io->surface_width-io->right_x_border+1.5+xwidth,ypos+0.5);
+               cairo_move_to(cr, io->pixmap_width-io->right_x_border+1.5, ypos+0.5);
+               cairo_line_to(cr, io->pixmap_width-io->right_x_border+1.5+xwidth,ypos+0.5);
                cairo_stroke(cr);
                cairo_destroy(cr);
                /* draw the labels */
@@ -976,7 +976,7 @@ io_stat_draw(io_stat_t *io)
 #else
                        cr = gdk_cairo_create (io->pixmap);
 #endif
-                       cairo_move_to (cr, io->surface_width-io->right_x_border+15+label_width-lwidth, ypos-label_height/2);
+                       cairo_move_to (cr, io->pixmap_width-io->right_x_border+15+label_width-lwidth, ypos-label_height/2);
                        pango_cairo_show_layout (cr, layout);
                        cairo_destroy (cr);
                        cr = NULL;
@@ -1006,8 +1006,8 @@ io_stat_draw(io_stat_t *io)
                cr = gdk_cairo_create (io->pixmap);
 #endif
                cairo_set_line_width (cr, 1.0);
-               cairo_move_to(cr, io->left_x_border+0.5, io->surface_height-bottom_y_border+1.5);
-               cairo_line_to(cr, io->surface_width-io->right_x_border+1.5,io->surface_height-bottom_y_border+1.5);
+               cairo_move_to(cr, io->left_x_border+0.5, io->pixmap_height-bottom_y_border+1.5);
+               cairo_line_to(cr, io->pixmap_width-io->right_x_border+1.5,io->pixmap_height-bottom_y_border+1.5);
                cairo_stroke(cr);
                cairo_destroy(cr);
        if((last_interval/io->interval)>=draw_width/io->pixels_per_tick){
@@ -1042,8 +1042,8 @@ io_stat_draw(io_stat_t *io)
                cr = gdk_cairo_create (io->pixmap);
 #endif
                cairo_set_line_width (cr, 1.0);
-               cairo_move_to(cr, x-1-io->pixels_per_tick/2+0.5, io->surface_height-bottom_y_border+1.5);
-               cairo_line_to(cr, x-1-io->pixels_per_tick/2+0.5, io->surface_height-bottom_y_border+xlen+1.5);
+               cairo_move_to(cr, x-1-io->pixels_per_tick/2+0.5, io->pixmap_height-bottom_y_border+1.5);
+               cairo_line_to(cr, x-1-io->pixels_per_tick/2+0.5, io->pixmap_height-bottom_y_border+xlen+1.5);
                cairo_stroke(cr);
                cairo_destroy(cr);
                if(xlen==10){
@@ -1054,8 +1054,8 @@ io_stat_draw(io_stat_t *io)
 
                        if ((x-1-io->pixels_per_tick/2-lwidth/2) < 5) {
                                x_pos=5;
-                       } else if ((x-1-io->pixels_per_tick/2+lwidth/2) > (io->surface_width-5)) {
-                               x_pos=io->surface_width-lwidth-5;
+                       } else if ((x-1-io->pixels_per_tick/2+lwidth/2) > (io->pixmap_width-5)) {
+                               x_pos=io->pixmap_width-lwidth-5;
                        } else {
                                x_pos=x-1-io->pixels_per_tick/2-lwidth/2;
                        }
@@ -1064,7 +1064,7 @@ io_stat_draw(io_stat_t *io)
 #else
                        cr = gdk_cairo_create (io->pixmap);
 #endif
-                       cairo_move_to (cr, x_pos, io->surface_height-bottom_y_border+15);
+                       cairo_move_to (cr, x_pos, io->pixmap_height-bottom_y_border+15);
                        pango_cairo_show_layout (cr, layout);
                        cairo_destroy (cr);
                        cr = NULL;
@@ -1199,7 +1199,7 @@ io_stat_draw(io_stat_t *io)
 #else
        gdk_cairo_set_source_pixmap (cr, io->pixmap, 0, 0);
 #endif
-       cairo_rectangle (cr, 0, 0, io->surface_width, io->surface_height);
+       cairo_rectangle (cr, 0, 0, io->pixmap_width, io->pixmap_height);
        cairo_fill (cr);
 
        cairo_destroy (cr);
@@ -1333,8 +1333,8 @@ iostat_init(const char *optarg _U_, void* userdata _U_)
 #endif
        io->scrollbar=NULL;
        io->scrollbar_adjustment=NULL;
-       io->surface_width=500;
-       io->surface_height=200;
+       io->pixmap_width=500;
+       io->pixmap_height=200;
        io->pixels_per_tick=pixels_per_tick[DEFAULT_PIXELS_PER_TICK_INDEX];
        io->max_y_units=AUTO_MAX_YSCALE;
        io->count_type=0;
@@ -1396,6 +1396,10 @@ draw_area_destroy_cb(GtkWidget *widget _U_, gpointer user_data)
 {
        io_stat_t *io = user_data;
        int i;
+       GtkWidget *save_bt = g_object_get_data(G_OBJECT(io->window), "save_bt");
+       surface_info_t *surface_info = g_object_get_data(G_OBJECT(save_bt), "surface-info");
+
+       g_free(surface_info);
 
        for(i=0;i<MAX_GRAPHS;i++){
                if(io->graphs[i].display){
@@ -1422,7 +1426,7 @@ pixmap_clicked_event(GtkWidget *widget _U_, GdkEventButton *event, gpointer user
        guint32 draw_width, interval, last_interval;
        guint frame_num;
 
-       draw_width=io->surface_width-io->right_x_border-io->left_x_border;
+       draw_width=io->pixmap_width-io->right_x_border-io->left_x_border;
 
        if ((event->x <= (draw_width+io->left_x_border+1-(draw_width/io->pixels_per_tick)*io->pixels_per_tick)) ||
            (event->x >= (draw_width+io->left_x_border-io->pixels_per_tick/2))) {
@@ -1463,6 +1467,9 @@ draw_area_configure_event(GtkWidget *widget, GdkEventConfigure *event _U_, gpoin
        GtkWidget *save_bt;
        GtkAllocation widget_alloc;
        cairo_t *cr;
+#if GTK_CHECK_VERSION(2,22,0)
+       surface_info_t *surface_info = g_new(surface_info_t, 1);
+#endif
 
 #if GTK_CHECK_VERSION(2,22,0)
        if(io->surface){
@@ -1489,12 +1496,15 @@ draw_area_configure_event(GtkWidget *widget, GdkEventConfigure *event _U_, gpoin
                        widget_alloc.height,
                        -1);
 #endif
-       io->surface_width=widget_alloc.width;
-       io->surface_height=widget_alloc.height;
+       io->pixmap_width=widget_alloc.width;
+       io->pixmap_height=widget_alloc.height;
 
        save_bt = g_object_get_data(G_OBJECT(io->window), "save_bt");
 #if GTK_CHECK_VERSION(2,22,0)
-       g_object_set_data(G_OBJECT(save_bt), "surface", io->surface);
+       surface_info->surface = io->surface;
+       surface_info->width = widget_alloc.width;
+       surface_info->height = widget_alloc.height;
+       g_object_set_data(G_OBJECT(save_bt), "surface-info", surface_info);
        gtk_widget_set_sensitive(save_bt, TRUE);
 
        cr = cairo_create (io->surface);
@@ -1560,7 +1570,7 @@ create_draw_area(io_stat_t *io, GtkWidget *box)
        io->draw_area=gtk_drawing_area_new();
        g_signal_connect(io->draw_area, "destroy", G_CALLBACK(draw_area_destroy_cb), io);
 
-       gtk_widget_set_size_request(io->draw_area, io->surface_width, io->surface_height);
+       gtk_widget_set_size_request(io->draw_area, io->pixmap_width, io->pixmap_height);
 
        /* signals needed to handle backing pixmap */
        g_signal_connect(io->draw_area, "expose-event", G_CALLBACK(draw_area_expose_event), io);
index 741833b3a1c2eebe5dd3d9e57083e4c30a983e65..3491c6beb996da98f5e7157ad546fe08ddb26704 100644 (file)
 #include "gtk/file_dlg.h"
 
 #include "gtk/old-gtk-compat.h"
-
+#if GTK_CHECK_VERSION(2,22,0)
+#if !GTK_CHECK_VERSION(3,0,0)
+#include "gtk/gui_utils.h"
+#endif
+#endif
 static GtkWidget *save_as_w;
 
 static void
@@ -55,7 +59,7 @@ pixbuf_save_button_cb(GtkWidget *save_as_w_lcl, GdkPixbuf *pixbuf)
 {
        gchar *filename, *file_type;
        GtkWidget *type_cm, *simple_w;
-        GError *error = NULL;
+    GError *error = NULL;
        gboolean ret;
 
        filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(save_as_w_lcl));
@@ -95,7 +99,11 @@ pixbuf_save_button_cb(GtkWidget *save_as_w_lcl, GdkPixbuf *pixbuf)
 void
 pixmap_save_cb(GtkWidget *w, gpointer pixmap_ptr _U_)
 {
-        GdkPixmap *pixmap = g_object_get_data(G_OBJECT(w), "pixmap");
+#if GTK_CHECK_VERSION(2,22,0)
+       surface_info_t *surface_info = g_object_get_data(G_OBJECT(w), "surface-info");
+#else
+    GdkPixmap *pixmap = g_object_get_data(G_OBJECT(w), "pixmap");
+#endif
        GdkPixbuf *pixbuf;
        GdkPixbufFormat *pixbuf_format;
        GtkWidget *main_vb, *save_as_type_hb, *type_lb, *type_cm;
@@ -106,9 +114,13 @@ pixmap_save_cb(GtkWidget *w, gpointer pixmap_ptr _U_)
        guint format_index = 0;
        guint default_index = 0;
 
+#if GTK_CHECK_VERSION(2,22,0)
+       pixbuf = gdk_pixbuf_get_from_surface (surface_info->surface,
+               0, 0, surface_info->width, surface_info->height);
+#else
        pixbuf = gdk_pixbuf_get_from_drawable(NULL, pixmap, NULL,
                                              0, 0, 0, 0, -1, -1);
-
+#endif
        if(!pixbuf) {
                simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                              "%sCould not get image from graph%s",
index 700c08897666b55e65b30581d143e3311c52930b..ec92f4f984d67376b17862dbce31cdc7fb4bc005 100644 (file)
@@ -30,4 +30,9 @@
  * asking for options to save the graph with (such as file type). */
 void pixmap_save_cb(GtkWidget *w, gpointer pixmap_ptr);
 
+typedef struct _surface_info_t {
+       cairo_surface_t *surface;
+       gint    width;
+       gint    height;
+} surface_info_t;
 #endif /* __PIXMAP_SAVE_H__ */