aboutsummaryrefslogtreecommitdiffstats
path: root/src/image.c
diff options
context:
space:
mode:
authorJan D2015-04-12 13:42:42 +0200
committerJan D2015-04-12 13:42:42 +0200
commitc744c8a8fc2ddea0f3e7d510f1a3c98876c51c05 (patch)
tree414429ce9272b43cdeb3b23e5aef41e39d538deb /src/image.c
parentac00e0a0bf4aac5b2443a7651853f3812251047f (diff)
downloademacs-c744c8a8fc2ddea0f3e7d510f1a3c98876c51c05.tar.gz
emacs-c744c8a8fc2ddea0f3e7d510f1a3c98876c51c05.zip
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.c226
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)
518 518
519#endif /* HAVE_X_WINDOWS */ 519#endif /* HAVE_X_WINDOWS */
520 520
521
522/*********************************************************************** 521/***********************************************************************
523 Image types 522 Image types
524 ***********************************************************************/ 523 ***********************************************************************/
@@ -1084,6 +1083,47 @@ image_ascent (struct image *img, struct face *face, struct glyph_slice *slice)
1084 return ascent; 1083 return ascent;
1085} 1084}
1086 1085
1086#ifdef USE_CAIRO
1087static uint32_t
1088get_spec_bg_or_alpha_as_argb (struct image *img,
1089 struct frame *f)
1090{
1091 uint32_t bgcolor = 0;
1092 XColor xbgcolor;
1093 Lisp_Object bg = image_spec_value (img->spec, QCbackground, NULL);
1094
1095 if (STRINGP (bg) && XParseColor (FRAME_X_DISPLAY (f),
1096 FRAME_X_COLORMAP (f),
1097 SSDATA (bg),
1098 &xbgcolor))
1099 bgcolor = (0xff << 24) | ((xbgcolor.red / 256) << 16)
1100 | ((xbgcolor.green / 256) << 8) | (xbgcolor.blue / 256);
1101 return bgcolor;
1102}
1103
1104static void
1105create_cairo_image_surface (struct image *img,
1106 unsigned char *data,
1107 int width,
1108 int height)
1109{
1110 cairo_surface_t *surface;
1111 cairo_format_t format = CAIRO_FORMAT_ARGB32;
1112 int stride = cairo_format_stride_for_width (format, width);
1113 surface = cairo_image_surface_create_for_data (data,
1114 format,
1115 width,
1116 height,
1117 stride);
1118 img->width = width;
1119 img->height = height;
1120 img->cr_data = surface;
1121 img->cr_data2 = data;
1122 img->pixmap = 0;
1123}
1124#endif
1125
1126
1087 1127
1088/* Image background colors. */ 1128/* Image background colors. */
1089 1129
@@ -3635,19 +3675,16 @@ xpm_load (struct frame *f, struct image *img)
3635 if (rc == XpmSuccess 3675 if (rc == XpmSuccess
3636 && img->ximg->format == ZPixmap 3676 && img->ximg->format == ZPixmap
3637 && img->ximg->bits_per_pixel == 32 3677 && img->ximg->bits_per_pixel == 32
3638 && img->mask_img->bits_per_pixel == 1) 3678 && (! img->mask_img || img->mask_img->bits_per_pixel == 1))
3639 { 3679 {
3640 cairo_surface_t *surface;
3641 int width = img->ximg->width; 3680 int width = img->ximg->width;
3642 int height = img->ximg->height; 3681 int height = img->ximg->height;
3643 cairo_format_t format = CAIRO_FORMAT_ARGB32; 3682 unsigned char *data = (unsigned char *) xmalloc (width*height*4);
3644 int stride = cairo_format_stride_for_width (format, width);
3645 unsigned char *data = (unsigned char *)
3646 xmalloc (width*height*4);
3647 int i; 3683 int i;
3648 uint32_t *od = (uint32_t *)data; 3684 uint32_t *od = (uint32_t *)data;
3649 uint32_t *id = (uint32_t *)img->ximg->data; 3685 uint32_t *id = (uint32_t *)img->ximg->data;
3650 unsigned char *mid = img->mask_img->data; 3686 unsigned char *mid = img->mask_img ? img->mask_img->data : 0;
3687 uint32_t bgcolor = get_spec_bg_or_alpha_as_argb (img, f);
3651 3688
3652 for (i = 0; i < height; ++i) 3689 for (i = 0; i < height; ++i)
3653 { 3690 {
@@ -3655,24 +3692,15 @@ xpm_load (struct frame *f, struct image *img)
3655 for (k = 0; k < width; ++k) 3692 for (k = 0; k < width; ++k)
3656 { 3693 {
3657 int idx = i * img->ximg->bytes_per_line/4 + k; 3694 int idx = i * img->ximg->bytes_per_line/4 + k;
3658 int maskidx = i * img->mask_img->bytes_per_line + k/8; 3695 int maskidx = mid ? i * img->mask_img->bytes_per_line + k/8 : 0;
3659 int mask = mid[maskidx] & (1 << (k % 8)); 3696 int mask = mid ? mid[maskidx] & (1 << (k % 8)) : 1;
3660 3697
3661 if (mask) od[idx] = id[idx] + 0xff000000; // ff => full alpha 3698 if (mask) od[idx] = id[idx] + 0xff000000; // ff => full alpha
3662 else od[idx] = 0; 3699 else od[idx] = bgcolor;
3663 } 3700 }
3664 } 3701 }
3665 3702
3666 surface = cairo_image_surface_create_for_data (data, 3703 create_cairo_image_surface (img, data, width, height);
3667 format,
3668 width,
3669 height,
3670 stride);
3671 img->width = cairo_image_surface_get_width (surface);
3672 img->height = cairo_image_surface_get_height (surface);
3673 img->cr_data = surface;
3674 img->pixmap = 0;
3675 img->cr_data2 = data;
3676 } 3704 }
3677 else 3705 else
3678 { 3706 {
@@ -5544,7 +5572,7 @@ png_image_p (Lisp_Object object)
5544#endif /* HAVE_PNG || HAVE_NS || USE_CAIRO */ 5572#endif /* HAVE_PNG || HAVE_NS || USE_CAIRO */
5545 5573
5546 5574
5547#if defined HAVE_PNG && !defined HAVE_NS && !defined USE_CAIRO 5575#if defined HAVE_PNG && !defined HAVE_NS
5548 5576
5549# ifdef WINDOWSNT 5577# ifdef WINDOWSNT
5550/* PNG library details. */ 5578/* PNG library details. */
@@ -5790,6 +5818,11 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5790 bool transparent_p; 5818 bool transparent_p;
5791 struct png_memory_storage tbr; /* Data to be read */ 5819 struct png_memory_storage tbr; /* Data to be read */
5792 5820
5821#ifdef USE_CAIRO
5822 unsigned char *data = 0;
5823 uint32_t *dataptr;
5824#endif
5825
5793 /* Find out what file to load. */ 5826 /* Find out what file to load. */
5794 specified_file = image_spec_value (img->spec, QCfile, NULL); 5827 specified_file = image_spec_value (img->spec, QCfile, NULL);
5795 specified_data = image_spec_value (img->spec, QCdata, NULL); 5828 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)
5908 goto error; 5941 goto error;
5909 } 5942 }
5910 5943
5944#ifndef USE_CAIRO
5911 /* Create the X image and pixmap now, so that the work below can be 5945 /* Create the X image and pixmap now, so that the work below can be
5912 omitted if the image is too large for X. */ 5946 omitted if the image is too large for X. */
5913 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) 5947 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
5914 goto error; 5948 goto error;
5949#endif
5915 5950
5916 /* If image contains simply transparency data, we prefer to 5951 /* If image contains simply transparency data, we prefer to
5917 construct a clipping mask. */ 5952 construct a clipping mask. */
@@ -5998,6 +6033,10 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5998 c->fp = NULL; 6033 c->fp = NULL;
5999 } 6034 }
6000 6035
6036#ifdef USE_CAIRO
6037 data = (unsigned char *) xmalloc (width * height * 4);
6038 dataptr = (uint32_t *) data;
6039#else
6001 /* Create an image and pixmap serving as mask if the PNG image 6040 /* Create an image and pixmap serving as mask if the PNG image
6002 contains an alpha channel. */ 6041 contains an alpha channel. */
6003 if (channels == 4 6042 if (channels == 4
@@ -6009,6 +6048,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
6009 x_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP); 6048 x_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP);
6010 goto error; 6049 goto error;
6011 } 6050 }
6051#endif
6012 6052
6013 /* Fill the X image and mask from PNG data. */ 6053 /* Fill the X image and mask from PNG data. */
6014 init_color_table (); 6054 init_color_table ();
@@ -6021,6 +6061,14 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
6021 { 6061 {
6022 int r, g, b; 6062 int r, g, b;
6023 6063
6064#ifdef USE_CAIRO
6065 int a = 0xff;
6066 r = *p++;
6067 g = *p++;
6068 b = *p++;
6069 if (channels == 4) a = *p++;
6070 *dataptr++ = (a << 24) | (r << 16) | (g << 8) | b;
6071#else
6024 r = *p++ << 8; 6072 r = *p++ << 8;
6025 g = *p++ << 8; 6073 g = *p++ << 8;
6026 b = *p++ << 8; 6074 b = *p++ << 8;
@@ -6047,6 +6095,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
6047 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN); 6095 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
6048 ++p; 6096 ++p;
6049 } 6097 }
6098#endif
6050 } 6099 }
6051 } 6100 }
6052 6101
@@ -6076,6 +6125,9 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
6076 img->width = width; 6125 img->width = width;
6077 img->height = height; 6126 img->height = height;
6078 6127
6128#ifdef USE_CAIRO
6129 create_cairo_image_surface (img, data, width, height);
6130#else
6079 /* Maybe fill in the background field while we have ximg handy. 6131 /* Maybe fill in the background field while we have ximg handy.
6080 Casting avoids a GCC warning. */ 6132 Casting avoids a GCC warning. */
6081 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg); 6133 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)
6092 6144
6093 image_put_x_image (f, img, mask_img, 1); 6145 image_put_x_image (f, img, mask_img, 1);
6094 } 6146 }
6147#endif
6095 6148
6096 return 1; 6149 return 1;
6097} 6150}
@@ -6113,44 +6166,8 @@ png_load (struct frame *f, struct image *img)
6113 image_spec_value (img->spec, QCdata, NULL)); 6166 image_spec_value (img->spec, QCdata, NULL));
6114} 6167}
6115 6168
6116#elif defined USE_CAIRO
6117 6169
6118static bool 6170#endif /* HAVE_NS */
6119png_load (struct frame *f, struct image *img)
6120{
6121 Lisp_Object file;
6122 Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL);
6123 cairo_surface_t *surface;
6124
6125 if (! STRINGP (specified_file))
6126 {
6127 image_error ("Invalid image spec, file missing `%s'", img->spec, Qnil);
6128 return false;
6129 }
6130
6131 file = x_find_image_file (specified_file);
6132 if (! STRINGP (file))
6133 {
6134 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6135 return false;
6136 }
6137
6138 surface = cairo_image_surface_create_from_png (SSDATA (file));
6139 if (! surface)
6140 {
6141 image_error ("Error creating surface from file `%s'",
6142 specified_file, Qnil);
6143 return false;
6144 }
6145 img->width = cairo_image_surface_get_width (surface);
6146 img->height = cairo_image_surface_get_height (surface);
6147 img->cr_data = surface;
6148 img->pixmap = 0;
6149
6150 return true;
6151}
6152
6153#endif /* USE_CAIRO */
6154 6171
6155 6172
6156 6173
@@ -6708,9 +6725,6 @@ jpeg_load_body (struct frame *f, struct image *img,
6708 JPOOL_IMAGE, row_stride, 1); 6725 JPOOL_IMAGE, row_stride, 1);
6709#ifdef USE_CAIRO 6726#ifdef USE_CAIRO
6710 { 6727 {
6711 cairo_surface_t *surface;
6712 cairo_format_t format = CAIRO_FORMAT_ARGB32;
6713 int stride = cairo_format_stride_for_width (format, width);
6714 unsigned char *data = (unsigned char *) xmalloc (width*height*4); 6728 unsigned char *data = (unsigned char *) xmalloc (width*height*4);
6715 uint32_t *dataptr = (uint32_t *) data; 6729 uint32_t *dataptr = (uint32_t *) data;
6716 int r, g, b; 6730 int r, g, b;
@@ -6729,17 +6743,7 @@ jpeg_load_body (struct frame *f, struct image *img,
6729 } 6743 }
6730 } 6744 }
6731 6745
6732 surface = cairo_image_surface_create_for_data (data, 6746 create_cairo_image_surface (img, data, width, height);
6733 format,
6734 width,
6735 height,
6736 stride);
6737
6738 img->width = width;
6739 img->height = height;
6740 img->cr_data = surface;
6741 img->cr_data2 = data;
6742 img->pixmap = 0;
6743 } 6747 }
6744#else 6748#else
6745 for (y = 0; y < height; ++y) 6749 for (y = 0; y < height; ++y)
@@ -7199,9 +7203,6 @@ tiff_load (struct frame *f, struct image *img)
7199 7203
7200#ifdef USE_CAIRO 7204#ifdef USE_CAIRO
7201 { 7205 {
7202 cairo_surface_t *surface;
7203 cairo_format_t format = CAIRO_FORMAT_ARGB32;
7204 int stride = cairo_format_stride_for_width (format, width);
7205 unsigned char *data = (unsigned char *) xmalloc (width*height*4); 7206 unsigned char *data = (unsigned char *) xmalloc (width*height*4);
7206 uint32_t *dataptr = (uint32_t *) data; 7207 uint32_t *dataptr = (uint32_t *) data;
7207 int r, g, b, a; 7208 int r, g, b, a;
@@ -7220,17 +7221,7 @@ tiff_load (struct frame *f, struct image *img)
7220 } 7221 }
7221 } 7222 }
7222 7223
7223 surface = cairo_image_surface_create_for_data (data, 7224 create_cairo_image_surface (img, data, width, height);
7224 format,
7225 width,
7226 height,
7227 stride);
7228
7229 img->width = width;
7230 img->height = height;
7231 img->cr_data = surface;
7232 img->cr_data2 = buf;
7233 img->pixmap = 0;
7234 } 7225 }
7235#else 7226#else
7236 /* Initialize the color table. */ 7227 /* Initialize the color table. */
@@ -7667,6 +7658,21 @@ gif_load (struct frame *f, struct image *img)
7667#ifdef USE_CAIRO 7658#ifdef USE_CAIRO
7668 /* xzalloc so data is zero => transparent */ 7659 /* xzalloc so data is zero => transparent */
7669 data = (unsigned char *) xzalloc (width * height * 4); 7660 data = (unsigned char *) xzalloc (width * height * 4);
7661 if (STRINGP (specified_bg))
7662 {
7663 XColor color;
7664 if (x_defined_color (f, SSDATA (specified_bg), &color, 0))
7665 {
7666 uint32_t *dataptr = (uint32_t *)data;
7667 int r = color.red/256;
7668 int g = color.green/256;
7669 int b = color.blue/256;
7670
7671 for (y = 0; y < height; ++y)
7672 for (x = 0; x < width; ++x)
7673 *dataptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
7674 }
7675 }
7670#else 7676#else
7671 /* Create the X image and pixmap. */ 7677 /* Create the X image and pixmap. */
7672 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) 7678 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)
7887 } 7893 }
7888 7894
7889#ifdef USE_CAIRO 7895#ifdef USE_CAIRO
7890 { 7896 create_cairo_image_surface (img, data, width, height);
7891 cairo_surface_t *surface;
7892 cairo_format_t format = CAIRO_FORMAT_ARGB32;
7893 int stride = cairo_format_stride_for_width (format, width);
7894
7895 surface = cairo_image_surface_create_for_data (data,
7896 format,
7897 width,
7898 height,
7899 stride);
7900
7901 img->width = width;
7902 img->height = height;
7903 img->cr_data = surface;
7904 img->cr_data2 = data;
7905 img->pixmap = 0;
7906 }
7907#else 7897#else
7908 /* Maybe fill in the background field while we have ximg handy. */ 7898 /* Maybe fill in the background field while we have ximg handy. */
7909 if (NILP (image_spec_value (img->spec, QCbackground, NULL))) 7899 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
@@ -9134,11 +9124,9 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. *
9134 9124
9135#ifdef USE_CAIRO 9125#ifdef USE_CAIRO
9136 { 9126 {
9137 cairo_surface_t *surface;
9138 cairo_format_t format = CAIRO_FORMAT_ARGB32;
9139 int stride = cairo_format_stride_for_width (format, width);
9140 unsigned char *data = (unsigned char *) xmalloc (width*height*4); 9127 unsigned char *data = (unsigned char *) xmalloc (width*height*4);
9141 int y; 9128 int y;
9129 uint32_t bgcolor = get_spec_bg_or_alpha_as_argb (img, f);
9142 9130
9143 for (y = 0; y < height; ++y) 9131 for (y = 0; y < height; ++y)
9144 { 9132 {
@@ -9148,27 +9136,21 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. *
9148 9136
9149 for (x = 0; x < width; ++x) 9137 for (x = 0; x < width; ++x)
9150 { 9138 {
9151 *dataptr = (iconptr[0] << 16) 9139 if (iconptr[3] == 0)
9152 | (iconptr[1] << 8) 9140 *dataptr = bgcolor;
9153 | iconptr[2] 9141 else
9154 | (iconptr[3] << 24); 9142 *dataptr = (iconptr[0] << 16)
9143 | (iconptr[1] << 8)
9144 | iconptr[2]
9145 | (iconptr[3] << 24);
9146
9155 iconptr += 4; 9147 iconptr += 4;
9156 ++dataptr; 9148 ++dataptr;
9157 } 9149 }
9158 } 9150 }
9159 9151
9160 surface = cairo_image_surface_create_for_data (data, 9152 create_cairo_image_surface (img, data, width, height);
9161 format,
9162 width,
9163 height,
9164 stride);
9165
9166 g_object_unref (pixbuf); 9153 g_object_unref (pixbuf);
9167 img->width = width;
9168 img->height = height;
9169 img->cr_data = surface;
9170 img->cr_data2 = data;
9171 img->pixmap = 0;
9172 } 9154 }
9173#else 9155#else
9174 /* Try to create a x pixmap to hold the svg pixmap. */ 9156 /* Try to create a x pixmap to hold the svg pixmap. */