diff options
author | Anders Broman <anders.broman@ericsson.com> | 2011-08-14 21:40:25 +0000 |
---|---|---|
committer | Anders Broman <anders.broman@ericsson.com> | 2011-08-14 21:40:25 +0000 |
commit | 05178612dee5abf2e00655b69e32f09658625f34 (patch) | |
tree | e9d9774bde269ab0cfbf348c956ee9704a775a19 | |
parent | a17cde69ecf02d30ed345493f91dbbb837ddee7f (diff) | |
download | wireshark-05178612dee5abf2e00655b69e32f09658625f34.tar.gz wireshark-05178612dee5abf2e00655b69e32f09658625f34.tar.bz2 wireshark-05178612dee5abf2e00655b69e32f09658625f34.zip |
Make save IO graph work, I had to make a local copy of
GTK 3.0 function gdk_pixbuf_get_from_surface() put in gui_util.c
svn path=/trunk/; revision=38541
-rw-r--r-- | gtk/gui_utils.c | 181 | ||||
-rw-r--r-- | gtk/gui_utils.h | 9 | ||||
-rw-r--r-- | gtk/io_stat.c | 74 | ||||
-rw-r--r-- | gtk/pixmap_save.c | 20 | ||||
-rw-r--r-- | gtk/pixmap_save.h | 5 |
5 files changed, 253 insertions, 36 deletions
diff --git a/gtk/gui_utils.c b/gtk/gui_utils.c index 7a9cdcf276..d6c21e4a21 100644 --- a/gtk/gui_utils.c +++ b/gtk/gui_utils.c @@ -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 diff --git a/gtk/gui_utils.h b/gtk/gui_utils.h index 5e24f646ae..ffe6cf4197 100644 --- a/gtk/gui_utils.h +++ b/gtk/gui_utils.h @@ -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__ */ diff --git a/gtk/io_stat.c b/gtk/io_stat.c index b325af5ac4..4813162ae2 100644 --- a/gtk/io_stat.c +++ b/gtk/io_stat.c @@ -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); diff --git a/gtk/pixmap_save.c b/gtk/pixmap_save.c index 741833b3a1..3491c6beb9 100644 --- a/gtk/pixmap_save.c +++ b/gtk/pixmap_save.c @@ -40,7 +40,11 @@ #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", diff --git a/gtk/pixmap_save.h b/gtk/pixmap_save.h index 700c088976..ec92f4f984 100644 --- a/gtk/pixmap_save.h +++ b/gtk/pixmap_save.h @@ -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__ */ |