diff options
author | YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> | 2019-05-28 17:31:57 +0900 |
---|---|---|
committer | YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> | 2019-05-28 17:31:57 +0900 |
commit | c617b4bf1e50bf33f0016bbcd5f502cc88150f26 (patch) | |
tree | 9ee54794d6c99b46cc04adc6ccd3a92b53c5bf74 | |
parent | f113512ffcd2bce6af6cc0f8f49df11d1dcf0fe9 (diff) | |
download | emacs-c617b4bf1e50bf33f0016bbcd5f502cc88150f26.tar.gz |
Support tool bar icon image also on GTK+2 with cairo
* src/gtkutil.c (xg_get_pixbuf_from_surface) [USE_CAIRO && !HAVE_GTK3]: New
function.
(xg_get_image_for_pixmap) [USE_CAIRO && !HAVE_GTK3]: Use it.
(xg_tool_item_stale_p, update_frame_tool_bar) [USE_CAIRO && !HAVE_GTK3]: Use
cairo code also on GTK+2.
-rw-r--r-- | src/gtkutil.c | 69 |
1 files changed, 64 insertions, 5 deletions
diff --git a/src/gtkutil.c b/src/gtkutil.c index 43918dd3da5..c6534585f8d 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -279,6 +279,51 @@ xg_get_pixbuf_from_pix_and_mask (struct frame *f, return icon_buf; } +#if defined USE_CAIRO && !defined HAVE_GTK3 +static GdkPixbuf * +xg_get_pixbuf_from_surface (struct frame *f, cairo_surface_t *surface) +{ + int width = cairo_image_surface_get_width (surface); + int height = cairo_image_surface_get_height (surface); + GdkPixbuf *icon_buf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, + width, height); + if (icon_buf) + { + guchar *pixels = gdk_pixbuf_get_pixels (icon_buf); + int rowstride = gdk_pixbuf_get_rowstride (icon_buf); + cairo_surface_t *icon_surface + = cairo_image_surface_create_for_data (pixels, CAIRO_FORMAT_ARGB32, + width, height, rowstride); + cairo_t *cr = cairo_create (icon_surface); + cairo_surface_destroy (icon_surface); + cairo_set_source_surface (cr, surface, 0, 0); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + cairo_destroy (cr); + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + guint32 argb = ((guint32 *) pixels)[x]; +#ifdef WORDS_BIGENDIAN + /* ARGB -> RGBA (gdk_pixbuf, big endian) */ + ((guint32 *) pixels)[x] = (argb << 8) | (argb >> 24); +#else /* !WORDS_BIGENDIAN */ + /* ARGB -> ABGR (gdk_pixbuf, little endian) */ + ((guint32 *) pixels)[x] = (( argb & 0xff00ff00) + | ((argb << 16) & 0x00ff0000) + | ((argb >> 16) & 0x000000ff)); +#endif /* !WORDS_BIGENDIAN */ + } + pixels += rowstride; + } + } + + return icon_buf; +} +#endif /* USE_CAIRO && !HAVE_GTK3 */ + static Lisp_Object file_for_image (Lisp_Object image) { @@ -311,7 +356,7 @@ xg_get_image_for_pixmap (struct frame *f, GtkWidget *widget, GtkImage *old_widget) { -#if defined USE_CAIRO && defined HAVE_GTK3 +#ifdef USE_CAIRO cairo_surface_t *surface; #else GdkPixbuf *icon_buf; @@ -343,15 +388,29 @@ xg_get_image_for_pixmap (struct frame *f, on a monochrome display, and sometimes bad on all displays with certain themes. */ -#if defined USE_CAIRO && defined HAVE_GTK3 +#ifdef USE_CAIRO surface = img->cr_data; if (surface) { +#ifdef HAVE_GTK3 if (! old_widget) old_widget = GTK_IMAGE (gtk_image_new_from_surface (surface)); else gtk_image_set_from_surface (old_widget, surface); +#else /* !HAVE_GTK3 */ + GdkPixbuf *icon_buf = xg_get_pixbuf_from_surface (f, surface); + + if (icon_buf) + { + if (! old_widget) + old_widget = GTK_IMAGE (gtk_image_new_from_pixbuf (icon_buf)); + else + gtk_image_set_from_pixbuf (old_widget, icon_buf); + + g_object_unref (G_OBJECT (icon_buf)); + } +#endif /* !HAVE_GTK3 */ } #else /* This is a workaround to make icons look good on pseudo color @@ -4689,7 +4748,7 @@ xg_tool_item_stale_p (GtkWidget *wbutton, const char *stock_name, { gpointer gold_img = g_object_get_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA); -#if defined USE_CAIRO && defined HAVE_GTK3 +#ifdef USE_CAIRO void *old_img = (void *) gold_img; if (old_img != img->cr_data) return 1; @@ -4990,7 +5049,7 @@ update_frame_tool_bar (struct frame *f) prepare_image_for_display (f, img); if (img->load_failed_p -#if defined USE_CAIRO && defined HAVE_GTK3 +#ifdef USE_CAIRO || img->cr_data == NULL #else || img->pixmap == None @@ -5045,7 +5104,7 @@ update_frame_tool_bar (struct frame *f) { w = xg_get_image_for_pixmap (f, img, x->widget, NULL); g_object_set_data (G_OBJECT (w), XG_TOOL_BAR_IMAGE_DATA, -#if defined USE_CAIRO && defined HAVE_GTK3 +#ifdef USE_CAIRO (gpointer)img->cr_data #else (gpointer)img->pixmap |