diff options
author | Jan D <jan.h.d@swipnet.se> | 2015-04-12 13:42:42 +0200 |
---|---|---|
committer | Jan D <jan.h.d@swipnet.se> | 2015-04-12 13:42:42 +0200 |
commit | c744c8a8fc2ddea0f3e7d510f1a3c98876c51c05 (patch) | |
tree | 414429ce9272b43cdeb3b23e5aef41e39d538deb /src/image.c | |
parent | ac00e0a0bf4aac5b2443a7651853f3812251047f (diff) | |
download | emacs-c744c8a8fc2ddea0f3e7d510f1a3c98876c51c05.tar.gz |
Handle specified bg in images. Use generic libpng code for PNG:s.
* src/image.c (get_spec_bg_or_alpha_as_argb)
(create_cairo_image_surface): New functions when USE_CAIRO.
(xpm_load): Call the above functions. Handle XPM without mask
when USE_CAIRO.
(png_load_body): Handle USE_CAIRO case.
(png_load): Remove USE_CAIRO specific fuction, modify png_load_body
instead.
(jpeg_load_body): Call create_cairo_image_surface.
(gif_load, svg_load_image): Handle specified background, call
create_cairo_image_surface.
* src/xterm.c (x_draw_image_glyph_string): Added missing USE_CAIRO.
Diffstat (limited to 'src/image.c')
-rw-r--r-- | src/image.c | 226 |
1 files changed, 104 insertions, 122 deletions
diff --git a/src/image.c b/src/image.c index 8b78157a645..fd4ae1e5938 100644 --- a/src/image.c +++ b/src/image.c @@ -518,7 +518,6 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id) #endif /* HAVE_X_WINDOWS */ - /*********************************************************************** Image types ***********************************************************************/ @@ -1084,6 +1083,47 @@ image_ascent (struct image *img, struct face *face, struct glyph_slice *slice) return ascent; } +#ifdef USE_CAIRO +static uint32_t +get_spec_bg_or_alpha_as_argb (struct image *img, + struct frame *f) +{ + uint32_t bgcolor = 0; + XColor xbgcolor; + Lisp_Object bg = image_spec_value (img->spec, QCbackground, NULL); + + if (STRINGP (bg) && XParseColor (FRAME_X_DISPLAY (f), + FRAME_X_COLORMAP (f), + SSDATA (bg), + &xbgcolor)) + bgcolor = (0xff << 24) | ((xbgcolor.red / 256) << 16) + | ((xbgcolor.green / 256) << 8) | (xbgcolor.blue / 256); + return bgcolor; +} + +static void +create_cairo_image_surface (struct image *img, + unsigned char *data, + int width, + int height) +{ + cairo_surface_t *surface; + cairo_format_t format = CAIRO_FORMAT_ARGB32; + int stride = cairo_format_stride_for_width (format, width); + surface = cairo_image_surface_create_for_data (data, + format, + width, + height, + stride); + img->width = width; + img->height = height; + img->cr_data = surface; + img->cr_data2 = data; + img->pixmap = 0; +} +#endif + + /* Image background colors. */ @@ -3635,19 +3675,16 @@ xpm_load (struct frame *f, struct image *img) if (rc == XpmSuccess && img->ximg->format == ZPixmap && img->ximg->bits_per_pixel == 32 - && img->mask_img->bits_per_pixel == 1) + && (! img->mask_img || img->mask_img->bits_per_pixel == 1)) { - cairo_surface_t *surface; int width = img->ximg->width; int height = img->ximg->height; - cairo_format_t format = CAIRO_FORMAT_ARGB32; - int stride = cairo_format_stride_for_width (format, width); - unsigned char *data = (unsigned char *) - xmalloc (width*height*4); + unsigned char *data = (unsigned char *) xmalloc (width*height*4); int i; uint32_t *od = (uint32_t *)data; uint32_t *id = (uint32_t *)img->ximg->data; - unsigned char *mid = img->mask_img->data; + unsigned char *mid = img->mask_img ? img->mask_img->data : 0; + uint32_t bgcolor = get_spec_bg_or_alpha_as_argb (img, f); for (i = 0; i < height; ++i) { @@ -3655,24 +3692,15 @@ xpm_load (struct frame *f, struct image *img) for (k = 0; k < width; ++k) { int idx = i * img->ximg->bytes_per_line/4 + k; - int maskidx = i * img->mask_img->bytes_per_line + k/8; - int mask = mid[maskidx] & (1 << (k % 8)); + int maskidx = mid ? i * img->mask_img->bytes_per_line + k/8 : 0; + int mask = mid ? mid[maskidx] & (1 << (k % 8)) : 1; if (mask) od[idx] = id[idx] + 0xff000000; // ff => full alpha - else od[idx] = 0; + else od[idx] = bgcolor; } } - surface = cairo_image_surface_create_for_data (data, - format, - width, - height, - stride); - img->width = cairo_image_surface_get_width (surface); - img->height = cairo_image_surface_get_height (surface); - img->cr_data = surface; - img->pixmap = 0; - img->cr_data2 = data; + create_cairo_image_surface (img, data, width, height); } else { @@ -5544,7 +5572,7 @@ png_image_p (Lisp_Object object) #endif /* HAVE_PNG || HAVE_NS || USE_CAIRO */ -#if defined HAVE_PNG && !defined HAVE_NS && !defined USE_CAIRO +#if defined HAVE_PNG && !defined HAVE_NS # ifdef WINDOWSNT /* PNG library details. */ @@ -5790,6 +5818,11 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) bool transparent_p; struct png_memory_storage tbr; /* Data to be read */ +#ifdef USE_CAIRO + unsigned char *data = 0; + uint32_t *dataptr; +#endif + /* Find out what file to load. */ specified_file = image_spec_value (img->spec, QCfile, NULL); specified_data = image_spec_value (img->spec, QCdata, NULL); @@ -5908,10 +5941,12 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) goto error; } +#ifndef USE_CAIRO /* Create the X image and pixmap now, so that the work below can be omitted if the image is too large for X. */ if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) goto error; +#endif /* If image contains simply transparency data, we prefer to construct a clipping mask. */ @@ -5998,6 +6033,10 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) c->fp = NULL; } +#ifdef USE_CAIRO + data = (unsigned char *) xmalloc (width * height * 4); + dataptr = (uint32_t *) data; +#else /* Create an image and pixmap serving as mask if the PNG image contains an alpha channel. */ if (channels == 4 @@ -6009,6 +6048,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) x_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP); goto error; } +#endif /* Fill the X image and mask from PNG data. */ init_color_table (); @@ -6021,6 +6061,14 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) { int r, g, b; +#ifdef USE_CAIRO + int a = 0xff; + r = *p++; + g = *p++; + b = *p++; + if (channels == 4) a = *p++; + *dataptr++ = (a << 24) | (r << 16) | (g << 8) | b; +#else r = *p++ << 8; g = *p++ << 8; b = *p++ << 8; @@ -6047,6 +6095,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN); ++p; } +#endif } } @@ -6076,6 +6125,9 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) img->width = width; img->height = height; +#ifdef USE_CAIRO + create_cairo_image_surface (img, data, width, height); +#else /* Maybe fill in the background field while we have ximg handy. Casting avoids a GCC warning. */ IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg); @@ -6092,6 +6144,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) image_put_x_image (f, img, mask_img, 1); } +#endif return 1; } @@ -6113,44 +6166,8 @@ png_load (struct frame *f, struct image *img) image_spec_value (img->spec, QCdata, NULL)); } -#elif defined USE_CAIRO -static bool -png_load (struct frame *f, struct image *img) -{ - Lisp_Object file; - Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL); - cairo_surface_t *surface; - - if (! STRINGP (specified_file)) - { - image_error ("Invalid image spec, file missing `%s'", img->spec, Qnil); - return false; - } - - file = x_find_image_file (specified_file); - if (! STRINGP (file)) - { - image_error ("Cannot find image file `%s'", specified_file, Qnil); - return false; - } - - surface = cairo_image_surface_create_from_png (SSDATA (file)); - if (! surface) - { - image_error ("Error creating surface from file `%s'", - specified_file, Qnil); - return false; - } - img->width = cairo_image_surface_get_width (surface); - img->height = cairo_image_surface_get_height (surface); - img->cr_data = surface; - img->pixmap = 0; - - return true; -} - -#endif /* USE_CAIRO */ +#endif /* HAVE_NS */ @@ -6708,9 +6725,6 @@ jpeg_load_body (struct frame *f, struct image *img, JPOOL_IMAGE, row_stride, 1); #ifdef USE_CAIRO { - cairo_surface_t *surface; - cairo_format_t format = CAIRO_FORMAT_ARGB32; - int stride = cairo_format_stride_for_width (format, width); unsigned char *data = (unsigned char *) xmalloc (width*height*4); uint32_t *dataptr = (uint32_t *) data; int r, g, b; @@ -6729,17 +6743,7 @@ jpeg_load_body (struct frame *f, struct image *img, } } - surface = cairo_image_surface_create_for_data (data, - format, - width, - height, - stride); - - img->width = width; - img->height = height; - img->cr_data = surface; - img->cr_data2 = data; - img->pixmap = 0; + create_cairo_image_surface (img, data, width, height); } #else for (y = 0; y < height; ++y) @@ -7199,9 +7203,6 @@ tiff_load (struct frame *f, struct image *img) #ifdef USE_CAIRO { - cairo_surface_t *surface; - cairo_format_t format = CAIRO_FORMAT_ARGB32; - int stride = cairo_format_stride_for_width (format, width); unsigned char *data = (unsigned char *) xmalloc (width*height*4); uint32_t *dataptr = (uint32_t *) data; int r, g, b, a; @@ -7220,17 +7221,7 @@ tiff_load (struct frame *f, struct image *img) } } - surface = cairo_image_surface_create_for_data (data, - format, - width, - height, - stride); - - img->width = width; - img->height = height; - img->cr_data = surface; - img->cr_data2 = buf; - img->pixmap = 0; + create_cairo_image_surface (img, data, width, height); } #else /* Initialize the color table. */ @@ -7667,6 +7658,21 @@ gif_load (struct frame *f, struct image *img) #ifdef USE_CAIRO /* xzalloc so data is zero => transparent */ data = (unsigned char *) xzalloc (width * height * 4); + if (STRINGP (specified_bg)) + { + XColor color; + if (x_defined_color (f, SSDATA (specified_bg), &color, 0)) + { + uint32_t *dataptr = (uint32_t *)data; + int r = color.red/256; + int g = color.green/256; + int b = color.blue/256; + + for (y = 0; y < height; ++y) + for (x = 0; x < width; ++x) + *dataptr++ = (0xff << 24) | (r << 16) | (g << 8) | b; + } + } #else /* Create the X image and pixmap. */ if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) @@ -7887,23 +7893,7 @@ gif_load (struct frame *f, struct image *img) } #ifdef USE_CAIRO - { - cairo_surface_t *surface; - cairo_format_t format = CAIRO_FORMAT_ARGB32; - int stride = cairo_format_stride_for_width (format, width); - - surface = cairo_image_surface_create_for_data (data, - format, - width, - height, - stride); - - img->width = width; - img->height = height; - img->cr_data = surface; - img->cr_data2 = data; - img->pixmap = 0; - } + create_cairo_image_surface (img, data, width, height); #else /* Maybe fill in the background field while we have ximg handy. */ if (NILP (image_spec_value (img->spec, QCbackground, NULL))) @@ -9134,11 +9124,9 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. * #ifdef USE_CAIRO { - cairo_surface_t *surface; - cairo_format_t format = CAIRO_FORMAT_ARGB32; - int stride = cairo_format_stride_for_width (format, width); unsigned char *data = (unsigned char *) xmalloc (width*height*4); int y; + uint32_t bgcolor = get_spec_bg_or_alpha_as_argb (img, f); for (y = 0; y < height; ++y) { @@ -9148,27 +9136,21 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. * for (x = 0; x < width; ++x) { - *dataptr = (iconptr[0] << 16) - | (iconptr[1] << 8) - | iconptr[2] - | (iconptr[3] << 24); + if (iconptr[3] == 0) + *dataptr = bgcolor; + else + *dataptr = (iconptr[0] << 16) + | (iconptr[1] << 8) + | iconptr[2] + | (iconptr[3] << 24); + iconptr += 4; ++dataptr; } } - surface = cairo_image_surface_create_for_data (data, - format, - width, - height, - stride); - + create_cairo_image_surface (img, data, width, height); g_object_unref (pixbuf); - img->width = width; - img->height = height; - img->cr_data = surface; - img->cr_data2 = data; - img->pixmap = 0; } #else /* Try to create a x pixmap to hold the svg pixmap. */ |