diff options
| author | YAMAMOTO Mitsuharu | 2019-05-29 17:58:04 +0900 |
|---|---|---|
| committer | YAMAMOTO Mitsuharu | 2019-05-29 17:58:43 +0900 |
| commit | c89900ebd79d8c4bf5fd5550de053f379abd60ef (patch) | |
| tree | 73e5d59325043b25306bad2670c0a55b8ef172c0 /src/image.c | |
| parent | 09dce0fd391571ab1b580d2818689d596a8b99de (diff) | |
| download | emacs-c89900ebd79d8c4bf5fd5550de053f379abd60ef.tar.gz emacs-c89900ebd79d8c4bf5fd5550de053f379abd60ef.zip | |
Rework cairo image support to improve consistency (Bug#35871)
* src/dispextern.h (Emacs_Pix_Container) [USE_CAIRO]: New struct. Also used
as aliases of Emacs_Pixmap and Emacs_Pix_Context.
(x_kill_gs_process) [USE_CAIRO]: #ifdef out extern.
(RGB_PIXEL_COLOR) [USE_CAIRO]: Define as unsigned long.
* src/image.c: Include stdint.h. On cairo, remove existing image support
code, use non-X11-specific code for XBM/XPM, and remove POSTSCRIPT support.
(PUT_PIXEL): New macro. Use it instead of XPutPixel when not specific to X11.
(GET_PIXEL, NO_PIXMAP, PIX_MASK_RETAIN, PIX_MASK_DRAW)
(RGB_TO_ULONG, ARGB_TO_ULONG, RED_FROM_ULONG)
(GREEN_FROM_ULONG, BLUE_FROM_ULONG, RED16_FROM_ULONG)
(GREEN16_FROM_ULONG, BLUE16_FROM_ULONG) [USE_CAIRO]: New macros.
(image_create_pix_container, image_pix_container_put_pixel)
(image_pix_context_get_pixel, image_pix_container_create_from_bitmap_data)
(cr_create_cr_surface_from_image) [USE_CAIRO]: New functions.
(image_create_x_image_and_pixmap_1, image_destroy_x_image)
(image_check_image_size): Extract X11-specific code from here ...
(x_create_x_image_and_pixmap, x_destroy_x_image)
(x_check_image_size) [HAVE_X_WINDOWS]: ... to here.
(x_create_bitmap_mask) [HAVE_X_WINDOWS]: Use them. Inline specialized version
of four_corners_best.
(prepare_image_for_display, image_clear_image_1, image_destroy_x_image)
(gui_put_x_image, image_put_x_image, image_get_x_image, image_unget_x_image)
(Create_Pixmap_From_Bitmap_Data, lookup_rgb_color)
(image_to_emacs_colors) [USE_CAIRO]: Add cairo support.
(image_background, png_load_body) [USE_CAIRO]: Use image_alloc_image_color for
img->background.
(image_sync_to_pixmaps) [USE_CAIRO]: #ifdef out function.
(Create_Pixmap_From_Bitmap_Data) [HAVE_X_WINDOWS]: Move image_check_image_size
call from here ...
(xbm_load_image): ... to here.
(xpm_load_image):
(image_build_heuristic_mask, pbm_load, gif_load) [USE_CAIRO]: Use
lookup_rgb_color for argument of PUT_PIXEL.
(image_pixmap_draw_cross) [HAVE_X_WINDOWS || USE_CAIRO]: New function.
(image_disable_image) [HAVE_X_WINDOWS || USE_CAIRO]: Use it.
(CrossForeground) [!HAVE_NTGUI && !HAVE_NS]: New macro.
(image_disable_image) [!HAVE_NTGUI && !HAVE_NS]: Use it.
* src/xterm.c (handle_one_xevent) <ClientMessage> [USE_CAIRO]: #ifdef out
x_kill_gs_process call.
(x_free_pixmap) [USE_CAIRO]: Free Emacs_Pix_Container and data it contains.
Diffstat (limited to 'src/image.c')
| -rw-r--r-- | src/image.c | 957 |
1 files changed, 454 insertions, 503 deletions
diff --git a/src/image.c b/src/image.c index 699bdfd4fa1..70ca1079f3f 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -30,6 +30,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 30 | 30 | ||
| 31 | #include <setjmp.h> | 31 | #include <setjmp.h> |
| 32 | 32 | ||
| 33 | #include <stdint.h> | ||
| 33 | #include <c-ctype.h> | 34 | #include <c-ctype.h> |
| 34 | #include <flexmember.h> | 35 | #include <flexmember.h> |
| 35 | 36 | ||
| @@ -67,13 +68,37 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 67 | 68 | ||
| 68 | #ifdef HAVE_X_WINDOWS | 69 | #ifdef HAVE_X_WINDOWS |
| 69 | typedef struct x_bitmap_record Bitmap_Record; | 70 | typedef struct x_bitmap_record Bitmap_Record; |
| 71 | #ifndef USE_CAIRO | ||
| 70 | #define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y) | 72 | #define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y) |
| 73 | #define PUT_PIXEL XPutPixel | ||
| 71 | #define NO_PIXMAP None | 74 | #define NO_PIXMAP None |
| 72 | 75 | ||
| 73 | #define PIX_MASK_RETAIN 0 | 76 | #define PIX_MASK_RETAIN 0 |
| 74 | #define PIX_MASK_DRAW 1 | 77 | #define PIX_MASK_DRAW 1 |
| 78 | #endif /* !USE_CAIRO */ | ||
| 75 | #endif /* HAVE_X_WINDOWS */ | 79 | #endif /* HAVE_X_WINDOWS */ |
| 76 | 80 | ||
| 81 | #ifdef USE_CAIRO | ||
| 82 | #define GET_PIXEL image_pix_context_get_pixel | ||
| 83 | #define PUT_PIXEL image_pix_container_put_pixel | ||
| 84 | #define NO_PIXMAP 0 | ||
| 85 | |||
| 86 | #define PIX_MASK_RETAIN 0 | ||
| 87 | #define PIX_MASK_DRAW 255 | ||
| 88 | |||
| 89 | #define RGB_TO_ULONG(r, g, b) (((r) << 16) | ((g) << 8) | (b)) | ||
| 90 | #define ARGB_TO_ULONG(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) | ||
| 91 | #define RED_FROM_ULONG(color) (((color) >> 16) & 0xff) | ||
| 92 | #define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff) | ||
| 93 | #define BLUE_FROM_ULONG(color) ((color) & 0xff) | ||
| 94 | #define RED16_FROM_ULONG(color) (RED_FROM_ULONG (color) * 0x101) | ||
| 95 | #define GREEN16_FROM_ULONG(color) (GREEN_FROM_ULONG (color) * 0x101) | ||
| 96 | #define BLUE16_FROM_ULONG(color) (BLUE_FROM_ULONG (color) * 0x101) | ||
| 97 | |||
| 98 | static unsigned long image_alloc_image_color (struct frame *, struct image *, | ||
| 99 | Lisp_Object, unsigned long); | ||
| 100 | #endif /* USE_CAIRO */ | ||
| 101 | |||
| 77 | #ifdef HAVE_NTGUI | 102 | #ifdef HAVE_NTGUI |
| 78 | 103 | ||
| 79 | /* We need (or want) w32.h only when we're _not_ compiling for Cygwin. */ | 104 | /* We need (or want) w32.h only when we're _not_ compiling for Cygwin. */ |
| @@ -84,6 +109,7 @@ typedef struct x_bitmap_record Bitmap_Record; | |||
| 84 | 109 | ||
| 85 | typedef struct w32_bitmap_record Bitmap_Record; | 110 | typedef struct w32_bitmap_record Bitmap_Record; |
| 86 | #define GET_PIXEL(ximg, x, y) GetPixel (ximg, x, y) | 111 | #define GET_PIXEL(ximg, x, y) GetPixel (ximg, x, y) |
| 112 | #define PUT_PIXEL XPutPixel | ||
| 87 | #define NO_PIXMAP 0 | 113 | #define NO_PIXMAP 0 |
| 88 | 114 | ||
| 89 | #define PIX_MASK_RETAIN 0 | 115 | #define PIX_MASK_RETAIN 0 |
| @@ -95,6 +121,7 @@ typedef struct w32_bitmap_record Bitmap_Record; | |||
| 95 | typedef struct ns_bitmap_record Bitmap_Record; | 121 | typedef struct ns_bitmap_record Bitmap_Record; |
| 96 | 122 | ||
| 97 | #define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y) | 123 | #define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y) |
| 124 | #define PUT_PIXEL XPutPixel | ||
| 98 | #define NO_PIXMAP 0 | 125 | #define NO_PIXMAP 0 |
| 99 | 126 | ||
| 100 | #define PIX_MASK_RETAIN 0 | 127 | #define PIX_MASK_RETAIN 0 |
| @@ -118,16 +145,109 @@ static void free_color_table (void); | |||
| 118 | static unsigned long *colors_in_color_table (int *n); | 145 | static unsigned long *colors_in_color_table (int *n); |
| 119 | #endif | 146 | #endif |
| 120 | 147 | ||
| 121 | /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap | 148 | #ifdef USE_CAIRO |
| 122 | id, which is just an int that this section returns. Bitmaps are | ||
| 123 | reference counted so they can be shared among frames. | ||
| 124 | 149 | ||
| 125 | Bitmap indices are guaranteed to be > 0, so a negative number can | 150 | static Emacs_Pix_Container |
| 126 | be used to indicate no bitmap. | 151 | image_create_pix_container (struct frame *f, unsigned int width, |
| 152 | unsigned int height, unsigned int depth) | ||
| 153 | { | ||
| 154 | Emacs_Pix_Container pimg; | ||
| 127 | 155 | ||
| 128 | If you use image_create_bitmap_from_data, then you must keep track | 156 | pimg = xmalloc (sizeof (*pimg)); |
| 129 | of the bitmaps yourself. That is, creating a bitmap from the same | 157 | pimg->width = width; |
| 130 | data more than once will not be caught. */ | 158 | pimg->height = height; |
| 159 | pimg->bits_per_pixel = depth == 1 ? 8 : 32; | ||
| 160 | pimg->bytes_per_line = cairo_format_stride_for_width ((depth == 1 | ||
| 161 | ? CAIRO_FORMAT_A8 | ||
| 162 | : CAIRO_FORMAT_RGB24), | ||
| 163 | width); | ||
| 164 | pimg->data = xmalloc (pimg->bytes_per_line * height); | ||
| 165 | |||
| 166 | return pimg; | ||
| 167 | } | ||
| 168 | |||
| 169 | static void | ||
| 170 | image_pix_container_put_pixel (Emacs_Pix_Container image, | ||
| 171 | int x, int y, unsigned long pixel) | ||
| 172 | { | ||
| 173 | if (image->bits_per_pixel == 32) | ||
| 174 | ((uint32_t *)(image->data + y * image->bytes_per_line))[x] = pixel; | ||
| 175 | else | ||
| 176 | ((uint8_t *)(image->data + y * image->bytes_per_line))[x] = pixel; | ||
| 177 | } | ||
| 178 | |||
| 179 | static unsigned long | ||
| 180 | image_pix_context_get_pixel (Emacs_Pix_Context image, int x, int y) | ||
| 181 | { | ||
| 182 | if (image->bits_per_pixel == 32) | ||
| 183 | return ((uint32_t *)(image->data + y * image->bytes_per_line))[x]; | ||
| 184 | else | ||
| 185 | return ((uint8_t *)(image->data + y * image->bytes_per_line))[x]; | ||
| 186 | } | ||
| 187 | |||
| 188 | static Emacs_Pix_Container | ||
| 189 | image_pix_container_create_from_bitmap_data (struct frame *f, | ||
| 190 | char *data, unsigned int width, | ||
| 191 | unsigned int height, | ||
| 192 | unsigned long fg, | ||
| 193 | unsigned long bg) | ||
| 194 | { | ||
| 195 | Emacs_Pix_Container pimg = image_create_pix_container (f, width, height, 0); | ||
| 196 | int bytes_per_line = (width + (CHAR_BIT - 1)) / CHAR_BIT; | ||
| 197 | |||
| 198 | for (int y = 0; y < height; y++) | ||
| 199 | { | ||
| 200 | for (int x = 0; x < width; x++) | ||
| 201 | PUT_PIXEL (pimg, x, y, | ||
| 202 | (data[x / CHAR_BIT] >> (x % CHAR_BIT)) & 1 ? fg : bg); | ||
| 203 | data += bytes_per_line; | ||
| 204 | } | ||
| 205 | |||
| 206 | return pimg; | ||
| 207 | } | ||
| 208 | |||
| 209 | static cairo_surface_t * | ||
| 210 | cr_create_cr_surface_from_image (struct frame *f, struct image *img) | ||
| 211 | { | ||
| 212 | Emacs_Pix_Container pimg = img->pixmap; | ||
| 213 | cairo_surface_t *surface; | ||
| 214 | |||
| 215 | if (img->mask) | ||
| 216 | { | ||
| 217 | int x, y; | ||
| 218 | |||
| 219 | for (y = 0; y < pimg->height; y++) | ||
| 220 | for (x = 0; x < pimg->width; x++) | ||
| 221 | { | ||
| 222 | unsigned long color, alpha; | ||
| 223 | int r, g, b; | ||
| 224 | |||
| 225 | color = GET_PIXEL (pimg, x, y); | ||
| 226 | alpha = GET_PIXEL (img->mask, x, y); | ||
| 227 | r = (RED_FROM_ULONG (color) * alpha + 0x7f) / 0xff; | ||
| 228 | g = (GREEN_FROM_ULONG (color) * alpha + 0x7f) / 0xff; | ||
| 229 | b = (BLUE_FROM_ULONG (color) * alpha + 0x7f) / 0xff; | ||
| 230 | PUT_PIXEL (pimg, x, y, ARGB_TO_ULONG (alpha, r, g, b)); | ||
| 231 | } | ||
| 232 | xfree (img->mask->data); | ||
| 233 | img->mask->data = NULL; | ||
| 234 | } | ||
| 235 | block_input (); | ||
| 236 | surface = cairo_image_surface_create_for_data ((unsigned char *) pimg->data, | ||
| 237 | (img->mask | ||
| 238 | ? CAIRO_FORMAT_ARGB32 | ||
| 239 | : CAIRO_FORMAT_RGB24), | ||
| 240 | pimg->width, pimg->height, | ||
| 241 | pimg->bytes_per_line); | ||
| 242 | static cairo_user_data_key_t key; | ||
| 243 | cairo_surface_set_user_data (surface, &key, pimg->data, xfree); | ||
| 244 | unblock_input (); | ||
| 245 | pimg->data = NULL; | ||
| 246 | |||
| 247 | return surface; | ||
| 248 | } | ||
| 249 | |||
| 250 | #endif /* USE_CAIRO */ | ||
| 131 | 251 | ||
| 132 | #ifdef HAVE_NS | 252 | #ifdef HAVE_NS |
| 133 | /* Use with images created by ns_image_for_XPM. */ | 253 | /* Use with images created by ns_image_for_XPM. */ |
| @@ -146,6 +266,16 @@ XPutPixel (Emacs_Pix_Container image, int x, int y, unsigned long pixel) | |||
| 146 | } | 266 | } |
| 147 | #endif /* HAVE_NS */ | 267 | #endif /* HAVE_NS */ |
| 148 | 268 | ||
| 269 | /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap | ||
| 270 | id, which is just an int that this section returns. Bitmaps are | ||
| 271 | reference counted so they can be shared among frames. | ||
| 272 | |||
| 273 | Bitmap indices are guaranteed to be > 0, so a negative number can | ||
| 274 | be used to indicate no bitmap. | ||
| 275 | |||
| 276 | If you use image_create_bitmap_from_data, then you must keep track | ||
| 277 | of the bitmaps yourself. That is, creating a bitmap from the same | ||
| 278 | data more than once will not be caught. */ | ||
| 149 | 279 | ||
| 150 | /* Functions to access the contents of a bitmap, given an id. */ | 280 | /* Functions to access the contents of a bitmap, given an id. */ |
| 151 | 281 | ||
| @@ -433,16 +563,17 @@ static void image_unget_x_image (struct image *, bool, Emacs_Pix_Container); | |||
| 433 | 563 | ||
| 434 | #ifdef HAVE_X_WINDOWS | 564 | #ifdef HAVE_X_WINDOWS |
| 435 | 565 | ||
| 566 | #ifndef USE_CAIRO | ||
| 436 | static void image_sync_to_pixmaps (struct frame *, struct image *); | 567 | static void image_sync_to_pixmaps (struct frame *, struct image *); |
| 568 | #endif /* !USE_CAIRO */ | ||
| 437 | 569 | ||
| 438 | /* Useful functions defined in the section | 570 | /* We are working on X-specific data structures here even with cairo. |
| 439 | `Image type independent image structures' below. */ | 571 | So we use X-specific versions of image construction/destruction |
| 440 | 572 | functions and inline the specific case of four_corners_best. */ | |
| 441 | static unsigned long four_corners_best (XImage *ximg, | ||
| 442 | int *corners, | ||
| 443 | unsigned long width, | ||
| 444 | unsigned long height); | ||
| 445 | 573 | ||
| 574 | static bool x_create_x_image_and_pixmap (struct frame *, int, int, int, | ||
| 575 | XImage **, Pixmap *); | ||
| 576 | static void x_destroy_x_image (XImage *); | ||
| 446 | 577 | ||
| 447 | /* Create a mask of a bitmap. Note is this not a perfect mask. | 578 | /* Create a mask of a bitmap. Note is this not a perfect mask. |
| 448 | It's nicer with some borders in this context */ | 579 | It's nicer with some borders in this context */ |
| @@ -454,7 +585,7 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id) | |||
| 454 | XImage *ximg, *mask_img; | 585 | XImage *ximg, *mask_img; |
| 455 | unsigned long width, height; | 586 | unsigned long width, height; |
| 456 | bool result; | 587 | bool result; |
| 457 | unsigned long bg; | 588 | unsigned long bg UNINIT; |
| 458 | unsigned long x, y, xp, xm, yp, ym; | 589 | unsigned long x, y, xp, xm, yp, ym; |
| 459 | GC gc; | 590 | GC gc; |
| 460 | 591 | ||
| @@ -477,8 +608,7 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id) | |||
| 477 | return; | 608 | return; |
| 478 | } | 609 | } |
| 479 | 610 | ||
| 480 | result = image_create_x_image_and_pixmap_1 (f, width, height, 1, | 611 | result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask); |
| 481 | &mask_img, &mask, NULL); | ||
| 482 | 612 | ||
| 483 | unblock_input (); | 613 | unblock_input (); |
| 484 | if (!result) | 614 | if (!result) |
| @@ -487,7 +617,23 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id) | |||
| 487 | return; | 617 | return; |
| 488 | } | 618 | } |
| 489 | 619 | ||
| 490 | bg = four_corners_best (ximg, NULL, width, height); | 620 | unsigned long corner_pixels[4]; |
| 621 | corner_pixels[0] = XGetPixel (ximg, 0, 0); | ||
| 622 | corner_pixels[1] = XGetPixel (ximg, width - 1, 0); | ||
| 623 | corner_pixels[2] = XGetPixel (ximg, width - 1, height - 1); | ||
| 624 | corner_pixels[3] = XGetPixel (ximg, 0, height - 1); | ||
| 625 | int i, best_count; | ||
| 626 | for (i = best_count = 0; i < 4; ++i) | ||
| 627 | { | ||
| 628 | int j, n; | ||
| 629 | |||
| 630 | for (j = n = 0; j < 4; ++j) | ||
| 631 | if (corner_pixels[i] == corner_pixels[j]) | ||
| 632 | ++n; | ||
| 633 | |||
| 634 | if (n > best_count) | ||
| 635 | bg = corner_pixels[i], best_count = n; | ||
| 636 | } | ||
| 491 | 637 | ||
| 492 | for (y = 0; y < ximg->height; ++y) | 638 | for (y = 0; y < ximg->height; ++y) |
| 493 | { | 639 | { |
| @@ -522,7 +668,7 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id) | |||
| 522 | dpyinfo->bitmaps[id - 1].mask = mask; | 668 | dpyinfo->bitmaps[id - 1].mask = mask; |
| 523 | 669 | ||
| 524 | XDestroyImage (ximg); | 670 | XDestroyImage (ximg); |
| 525 | image_destroy_x_image (mask_img); | 671 | x_destroy_x_image (mask_img); |
| 526 | } | 672 | } |
| 527 | 673 | ||
| 528 | #endif /* HAVE_X_WINDOWS */ | 674 | #endif /* HAVE_X_WINDOWS */ |
| @@ -1015,13 +1161,22 @@ prepare_image_for_display (struct frame *f, struct image *img) | |||
| 1015 | /* We're about to display IMG, so set its timestamp to `now'. */ | 1161 | /* We're about to display IMG, so set its timestamp to `now'. */ |
| 1016 | img->timestamp = current_timespec (); | 1162 | img->timestamp = current_timespec (); |
| 1017 | 1163 | ||
| 1018 | #ifndef USE_CAIRO | ||
| 1019 | /* If IMG doesn't have a pixmap yet, load it now, using the image | 1164 | /* If IMG doesn't have a pixmap yet, load it now, using the image |
| 1020 | type dependent loader function. */ | 1165 | type dependent loader function. */ |
| 1021 | if (img->pixmap == NO_PIXMAP && !img->load_failed_p) | 1166 | if (img->pixmap == NO_PIXMAP && !img->load_failed_p) |
| 1022 | img->load_failed_p = ! img->type->load (f, img); | 1167 | img->load_failed_p = ! img->type->load (f, img); |
| 1023 | 1168 | ||
| 1024 | #ifdef HAVE_X_WINDOWS | 1169 | #ifdef USE_CAIRO |
| 1170 | if (!img->load_failed_p && img->cr_data == NULL) | ||
| 1171 | { | ||
| 1172 | img->cr_data = cr_create_cr_surface_from_image (f, img); | ||
| 1173 | if (img->cr_data == NULL) | ||
| 1174 | { | ||
| 1175 | img->load_failed_p = 1; | ||
| 1176 | img->type->free (f, img); | ||
| 1177 | } | ||
| 1178 | } | ||
| 1179 | #elif defined HAVE_X_WINDOWS | ||
| 1025 | if (!img->load_failed_p) | 1180 | if (!img->load_failed_p) |
| 1026 | { | 1181 | { |
| 1027 | block_input (); | 1182 | block_input (); |
| @@ -1029,7 +1184,6 @@ prepare_image_for_display (struct frame *f, struct image *img) | |||
| 1029 | unblock_input (); | 1184 | unblock_input (); |
| 1030 | } | 1185 | } |
| 1031 | #endif | 1186 | #endif |
| 1032 | #endif | ||
| 1033 | } | 1187 | } |
| 1034 | 1188 | ||
| 1035 | 1189 | ||
| @@ -1076,48 +1230,6 @@ image_ascent (struct image *img, struct face *face, struct glyph_slice *slice) | |||
| 1076 | return ascent; | 1230 | return ascent; |
| 1077 | } | 1231 | } |
| 1078 | 1232 | ||
| 1079 | #ifdef USE_CAIRO | ||
| 1080 | static uint32_t | ||
| 1081 | emacs_color_to_argb32 (Emacs_Color *ec) | ||
| 1082 | { | ||
| 1083 | return ((0xffu << 24) | ((ec->red / 256) << 16) | ||
| 1084 | | ((ec->green / 256) << 8) | (ec->blue / 256)); | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | static uint32_t | ||
| 1088 | get_spec_bg_or_alpha_as_argb (struct image *img, | ||
| 1089 | struct frame *f) | ||
| 1090 | { | ||
| 1091 | uint32_t bgcolor = 0; | ||
| 1092 | Emacs_Color xbgcolor; | ||
| 1093 | Lisp_Object bg = image_spec_value (img->spec, QCbackground, NULL); | ||
| 1094 | |||
| 1095 | if (STRINGP (bg) && x_parse_color (f, SSDATA (bg), &xbgcolor)) | ||
| 1096 | bgcolor = emacs_color_to_argb32 (&xbgcolor); | ||
| 1097 | |||
| 1098 | return bgcolor; | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | static cairo_surface_t * | ||
| 1102 | create_cairo_image_surface (int width, int height) | ||
| 1103 | { | ||
| 1104 | cairo_format_t format = CAIRO_FORMAT_ARGB32; | ||
| 1105 | eassert (cairo_format_stride_for_width (format, width) == width * 4); | ||
| 1106 | |||
| 1107 | return cairo_image_surface_create (format, width, height); | ||
| 1108 | } | ||
| 1109 | |||
| 1110 | static void | ||
| 1111 | set_cairo_image_surface (struct image *img, cairo_surface_t *surface) | ||
| 1112 | { | ||
| 1113 | cairo_surface_mark_dirty (surface); | ||
| 1114 | img->width = cairo_image_surface_get_width (surface); | ||
| 1115 | img->height = cairo_image_surface_get_height (surface); | ||
| 1116 | img->cr_data = surface; | ||
| 1117 | img->pixmap = 0; | ||
| 1118 | } | ||
| 1119 | #endif | ||
| 1120 | |||
| 1121 | 1233 | ||
| 1122 | 1234 | ||
| 1123 | /* Image background colors. */ | 1235 | /* Image background colors. */ |
| @@ -1184,7 +1296,19 @@ image_background (struct image *img, struct frame *f, Emacs_Pix_Context pimg) | |||
| 1184 | if (free_pimg) | 1296 | if (free_pimg) |
| 1185 | pimg = image_get_x_image_or_dc (f, img, 0, &prev); | 1297 | pimg = image_get_x_image_or_dc (f, img, 0, &prev); |
| 1186 | 1298 | ||
| 1187 | img->background = four_corners_best (pimg, img->corners, img->width, img->height); | 1299 | RGB_PIXEL_COLOR bg |
| 1300 | = four_corners_best (pimg, img->corners, img->width, img->height); | ||
| 1301 | #ifdef USE_CAIRO | ||
| 1302 | { | ||
| 1303 | char color_name[30]; | ||
| 1304 | sprintf (color_name, "#%04x%04x%04x", | ||
| 1305 | (unsigned int) RED16_FROM_ULONG (bg), | ||
| 1306 | (unsigned int) GREEN16_FROM_ULONG (bg), | ||
| 1307 | (unsigned int) BLUE16_FROM_ULONG (bg)); | ||
| 1308 | bg = image_alloc_image_color (f, img, build_string (color_name), 0); | ||
| 1309 | } | ||
| 1310 | #endif | ||
| 1311 | img->background = bg; | ||
| 1188 | 1312 | ||
| 1189 | if (free_pimg) | 1313 | if (free_pimg) |
| 1190 | image_unget_x_image_or_dc (img, 0, pimg, prev); | 1314 | image_unget_x_image_or_dc (img, 0, pimg, prev); |
| @@ -1259,7 +1383,7 @@ image_clear_image_1 (struct frame *f, struct image *img, int flags) | |||
| 1259 | /* NOTE (HAVE_NS): background color is NOT an indexed color! */ | 1383 | /* NOTE (HAVE_NS): background color is NOT an indexed color! */ |
| 1260 | img->background_valid = 0; | 1384 | img->background_valid = 0; |
| 1261 | } | 1385 | } |
| 1262 | #ifdef HAVE_X_WINDOWS | 1386 | #if defined HAVE_X_WINDOWS && !defined USE_CAIRO |
| 1263 | if (img->ximg) | 1387 | if (img->ximg) |
| 1264 | { | 1388 | { |
| 1265 | image_destroy_x_image (img->ximg); | 1389 | image_destroy_x_image (img->ximg); |
| @@ -1277,7 +1401,7 @@ image_clear_image_1 (struct frame *f, struct image *img, int flags) | |||
| 1277 | img->mask = NO_PIXMAP; | 1401 | img->mask = NO_PIXMAP; |
| 1278 | img->background_transparent_valid = 0; | 1402 | img->background_transparent_valid = 0; |
| 1279 | } | 1403 | } |
| 1280 | #ifdef HAVE_X_WINDOWS | 1404 | #if defined HAVE_X_WINDOWS && !defined USE_CAIRO |
| 1281 | if (img->mask_img) | 1405 | if (img->mask_img) |
| 1282 | { | 1406 | { |
| 1283 | image_destroy_x_image (img->mask_img); | 1407 | image_destroy_x_image (img->mask_img); |
| @@ -1290,14 +1414,21 @@ image_clear_image_1 (struct frame *f, struct image *img, int flags) | |||
| 1290 | if ((flags & CLEAR_IMAGE_COLORS) && img->ncolors) | 1414 | if ((flags & CLEAR_IMAGE_COLORS) && img->ncolors) |
| 1291 | { | 1415 | { |
| 1292 | /* W32_TODO: color table support. */ | 1416 | /* W32_TODO: color table support. */ |
| 1293 | #ifdef HAVE_X_WINDOWS | 1417 | #if defined HAVE_X_WINDOWS && !defined USE_CAIRO |
| 1294 | x_free_colors (f, img->colors, img->ncolors); | 1418 | x_free_colors (f, img->colors, img->ncolors); |
| 1295 | #endif /* HAVE_X_WINDOWS */ | 1419 | #endif /* HAVE_X_WINDOWS && !USE_CAIRO */ |
| 1296 | xfree (img->colors); | 1420 | xfree (img->colors); |
| 1297 | img->colors = NULL; | 1421 | img->colors = NULL; |
| 1298 | img->ncolors = 0; | 1422 | img->ncolors = 0; |
| 1299 | } | 1423 | } |
| 1300 | 1424 | ||
| 1425 | #ifdef USE_CAIRO | ||
| 1426 | if (img->cr_data) | ||
| 1427 | { | ||
| 1428 | cairo_surface_destroy ((cairo_surface_t *) img->cr_data); | ||
| 1429 | img->cr_data = NULL; | ||
| 1430 | } | ||
| 1431 | #endif /* USE_CAIRO */ | ||
| 1301 | } | 1432 | } |
| 1302 | 1433 | ||
| 1303 | /* Free X resources of image IMG which is used on frame F. */ | 1434 | /* Free X resources of image IMG which is used on frame F. */ |
| @@ -1306,10 +1437,6 @@ static void | |||
| 1306 | image_clear_image (struct frame *f, struct image *img) | 1437 | image_clear_image (struct frame *f, struct image *img) |
| 1307 | { | 1438 | { |
| 1308 | block_input (); | 1439 | block_input (); |
| 1309 | #ifdef USE_CAIRO | ||
| 1310 | if (img->cr_data) | ||
| 1311 | cairo_surface_destroy ((cairo_surface_t *)img->cr_data); | ||
| 1312 | #endif | ||
| 1313 | image_clear_image_1 (f, img, | 1440 | image_clear_image_1 (f, img, |
| 1314 | CLEAR_IMAGE_PIXMAP | CLEAR_IMAGE_MASK | CLEAR_IMAGE_COLORS); | 1441 | CLEAR_IMAGE_PIXMAP | CLEAR_IMAGE_MASK | CLEAR_IMAGE_COLORS); |
| 1315 | unblock_input (); | 1442 | unblock_input (); |
| @@ -2000,14 +2127,10 @@ mark_image_cache (struct image_cache *c) | |||
| 2000 | X / NS / W32 support code | 2127 | X / NS / W32 support code |
| 2001 | ***********************************************************************/ | 2128 | ***********************************************************************/ |
| 2002 | 2129 | ||
| 2003 | /* Return true if XIMG's size WIDTH x HEIGHT doesn't break the | 2130 | #ifdef HAVE_X_WINDOWS |
| 2004 | windowing system. | ||
| 2005 | WIDTH and HEIGHT must both be positive. | ||
| 2006 | If XIMG is null, assume it is a bitmap. */ | ||
| 2007 | static bool | 2131 | static bool |
| 2008 | image_check_image_size (Emacs_Pix_Container ximg, int width, int height) | 2132 | x_check_image_size (XImage *ximg, int width, int height) |
| 2009 | { | 2133 | { |
| 2010 | #ifdef HAVE_X_WINDOWS | ||
| 2011 | /* Respect Xlib's limits: it cannot deal with images that have more | 2134 | /* Respect Xlib's limits: it cannot deal with images that have more |
| 2012 | than INT_MAX (and/or UINT_MAX) bytes. And respect Emacs's limits | 2135 | than INT_MAX (and/or UINT_MAX) bytes. And respect Emacs's limits |
| 2013 | of PTRDIFF_MAX (and/or SIZE_MAX) bytes for any object. */ | 2136 | of PTRDIFF_MAX (and/or SIZE_MAX) bytes for any object. */ |
| @@ -2032,29 +2155,12 @@ image_check_image_size (Emacs_Pix_Container ximg, int width, int height) | |||
| 2032 | } | 2155 | } |
| 2033 | return (width <= (INT_MAX - (bitmap_pad - 1)) / depth | 2156 | return (width <= (INT_MAX - (bitmap_pad - 1)) / depth |
| 2034 | && height <= X_IMAGE_BYTES_MAX / bytes_per_line); | 2157 | && height <= X_IMAGE_BYTES_MAX / bytes_per_line); |
| 2035 | #else | ||
| 2036 | /* FIXME: Implement this check for the HAVE_NS and HAVE_NTGUI cases. | ||
| 2037 | For now, assume that every image size is allowed on these systems. */ | ||
| 2038 | return 1; | ||
| 2039 | #endif | ||
| 2040 | } | 2158 | } |
| 2041 | 2159 | ||
| 2042 | /* Create an Emacs_Pix_Container and a pixmap of size WIDTH x | ||
| 2043 | HEIGHT for use on frame F. Set *PIMG and *PIXMAP to the | ||
| 2044 | Emacs_Pix_Container and Emacs_Pixmap created. Set (*PIMG)->data | ||
| 2045 | to a raster of WIDTH x HEIGHT pixels allocated via xmalloc. Print | ||
| 2046 | error messages via image_error if an error occurs. Value is true | ||
| 2047 | if successful. | ||
| 2048 | |||
| 2049 | On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH | ||
| 2050 | should indicate the bit depth of the image. */ | ||
| 2051 | |||
| 2052 | static bool | 2160 | static bool |
| 2053 | image_create_x_image_and_pixmap_1 (struct frame *f, int width, int height, int depth, | 2161 | x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, |
| 2054 | Emacs_Pix_Container *pimg, | 2162 | XImage **ximg, Pixmap *pixmap) |
| 2055 | Emacs_Pixmap *pixmap, Picture *picture) | ||
| 2056 | { | 2163 | { |
| 2057 | #ifdef HAVE_X_WINDOWS | ||
| 2058 | Display *display = FRAME_X_DISPLAY (f); | 2164 | Display *display = FRAME_X_DISPLAY (f); |
| 2059 | Drawable drawable = FRAME_X_DRAWABLE (f); | 2165 | Drawable drawable = FRAME_X_DRAWABLE (f); |
| 2060 | Screen *screen = FRAME_X_SCREEN (f); | 2166 | Screen *screen = FRAME_X_SCREEN (f); |
| @@ -2063,38 +2169,104 @@ image_create_x_image_and_pixmap_1 (struct frame *f, int width, int height, int d | |||
| 2063 | 2169 | ||
| 2064 | if (depth <= 0) | 2170 | if (depth <= 0) |
| 2065 | depth = DefaultDepthOfScreen (screen); | 2171 | depth = DefaultDepthOfScreen (screen); |
| 2066 | *pimg = XCreateImage (display, DefaultVisualOfScreen (screen), | 2172 | *ximg = XCreateImage (display, DefaultVisualOfScreen (screen), |
| 2067 | depth, ZPixmap, 0, NULL, width, height, | 2173 | depth, ZPixmap, 0, NULL, width, height, |
| 2068 | depth > 16 ? 32 : depth > 8 ? 16 : 8, 0); | 2174 | depth > 16 ? 32 : depth > 8 ? 16 : 8, 0); |
| 2069 | if (*pimg == NULL) | 2175 | if (*ximg == NULL) |
| 2070 | { | 2176 | { |
| 2071 | image_error ("Unable to allocate X image"); | 2177 | image_error ("Unable to allocate X image"); |
| 2072 | return 0; | 2178 | return 0; |
| 2073 | } | 2179 | } |
| 2074 | 2180 | ||
| 2075 | if (! image_check_image_size (*pimg, width, height)) | 2181 | if (! x_check_image_size (*ximg, width, height)) |
| 2076 | { | 2182 | { |
| 2077 | image_destroy_x_image (*pimg); | 2183 | x_destroy_x_image (*ximg); |
| 2078 | *pimg = NULL; | 2184 | *ximg = NULL; |
| 2079 | image_error ("Image too large (%dx%d)", | 2185 | image_error ("Image too large (%dx%d)", |
| 2080 | make_fixnum (width), make_fixnum (height)); | 2186 | make_fixnum (width), make_fixnum (height)); |
| 2081 | return 0; | 2187 | return 0; |
| 2082 | } | 2188 | } |
| 2083 | 2189 | ||
| 2084 | /* Allocate image raster. */ | 2190 | /* Allocate image raster. */ |
| 2085 | (*pimg)->data = xmalloc ((*pimg)->bytes_per_line * height); | 2191 | (*ximg)->data = xmalloc ((*ximg)->bytes_per_line * height); |
| 2086 | 2192 | ||
| 2087 | /* Allocate a pixmap of the same size. */ | 2193 | /* Allocate a pixmap of the same size. */ |
| 2088 | *pixmap = XCreatePixmap (display, drawable, width, height, depth); | 2194 | *pixmap = XCreatePixmap (display, drawable, width, height, depth); |
| 2089 | if (*pixmap == NO_PIXMAP) | 2195 | if (*pixmap == NO_PIXMAP) |
| 2090 | { | 2196 | { |
| 2091 | image_destroy_x_image (*pimg); | 2197 | x_destroy_x_image (*ximg); |
| 2092 | *pimg = NULL; | 2198 | *ximg = NULL; |
| 2093 | image_error ("Unable to create X pixmap"); | 2199 | image_error ("Unable to create X pixmap"); |
| 2094 | return 0; | 2200 | return 0; |
| 2095 | } | 2201 | } |
| 2096 | 2202 | ||
| 2203 | return 1; | ||
| 2204 | } | ||
| 2205 | |||
| 2206 | static void | ||
| 2207 | x_destroy_x_image (XImage *ximg) | ||
| 2208 | { | ||
| 2209 | eassert (input_blocked_p ()); | ||
| 2210 | if (ximg) | ||
| 2211 | { | ||
| 2212 | xfree (ximg->data); | ||
| 2213 | ximg->data = NULL; | ||
| 2214 | } | ||
| 2215 | } | ||
| 2216 | |||
| 2217 | #endif /* HAVE_X_WINDOWS */ | ||
| 2218 | |||
| 2219 | /* Return true if XIMG's size WIDTH x HEIGHT doesn't break the | ||
| 2220 | windowing system. | ||
| 2221 | WIDTH and HEIGHT must both be positive. | ||
| 2222 | If XIMG is null, assume it is a bitmap. */ | ||
| 2223 | |||
| 2224 | static bool | ||
| 2225 | image_check_image_size (Emacs_Pix_Container ximg, int width, int height) | ||
| 2226 | { | ||
| 2227 | #if defined HAVE_X_WINDOWS && !defined USE_CAIRO | ||
| 2228 | return x_check_image_size (ximg, width, height); | ||
| 2229 | #else | ||
| 2230 | /* FIXME: Implement this check for the HAVE_NS and HAVE_NTGUI cases. | ||
| 2231 | For now, assume that every image size is allowed on these systems. */ | ||
| 2232 | return 1; | ||
| 2233 | #endif | ||
| 2234 | } | ||
| 2235 | |||
| 2236 | /* Create an Emacs_Pix_Container and a pixmap of size WIDTH x | ||
| 2237 | HEIGHT for use on frame F. Set *PIMG and *PIXMAP to the | ||
| 2238 | Emacs_Pix_Container and Emacs_Pixmap created. Set (*PIMG)->data | ||
| 2239 | to a raster of WIDTH x HEIGHT pixels allocated via xmalloc. Print | ||
| 2240 | error messages via image_error if an error occurs. Value is true | ||
| 2241 | if successful. | ||
| 2242 | |||
| 2243 | On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH | ||
| 2244 | should indicate the bit depth of the image. */ | ||
| 2245 | |||
| 2246 | static bool | ||
| 2247 | image_create_x_image_and_pixmap_1 (struct frame *f, int width, int height, int depth, | ||
| 2248 | Emacs_Pix_Container *pimg, | ||
| 2249 | Emacs_Pixmap *pixmap, Picture *picture) | ||
| 2250 | { | ||
| 2251 | #ifdef USE_CAIRO | ||
| 2252 | eassert (input_blocked_p ()); | ||
| 2253 | |||
| 2254 | /* Allocate a pixmap of the same size. */ | ||
| 2255 | *pixmap = image_create_pix_container (f, width, height, depth); | ||
| 2256 | if (*pixmap == NO_PIXMAP) | ||
| 2257 | { | ||
| 2258 | *pimg = NULL; | ||
| 2259 | image_error ("Unable to create X pixmap", Qnil, Qnil); | ||
| 2260 | return 0; | ||
| 2261 | } | ||
| 2262 | |||
| 2263 | *pimg = *pixmap; | ||
| 2264 | return 1; | ||
| 2265 | #elif defined HAVE_X_WINDOWS | ||
| 2266 | if (!x_create_x_image_and_pixmap (f, width, height, depth, pimg, pixmap)) | ||
| 2267 | return 0; | ||
| 2097 | # ifdef HAVE_XRENDER | 2268 | # ifdef HAVE_XRENDER |
| 2269 | Display *display = FRAME_X_DISPLAY (f); | ||
| 2098 | int event_basep, error_basep; | 2270 | int event_basep, error_basep; |
| 2099 | if (picture && XRenderQueryExtension (display, &event_basep, &error_basep)) | 2271 | if (picture && XRenderQueryExtension (display, &event_basep, &error_basep)) |
| 2100 | { | 2272 | { |
| @@ -2238,14 +2410,14 @@ image_create_x_image_and_pixmap_1 (struct frame *f, int width, int height, int d | |||
| 2238 | static void | 2410 | static void |
| 2239 | image_destroy_x_image (Emacs_Pix_Container pimg) | 2411 | image_destroy_x_image (Emacs_Pix_Container pimg) |
| 2240 | { | 2412 | { |
| 2413 | #if defined HAVE_X_WINDOWS && !defined USE_CAIRO | ||
| 2414 | x_destroy_x_image (pimg); | ||
| 2415 | #else | ||
| 2241 | eassert (input_blocked_p ()); | 2416 | eassert (input_blocked_p ()); |
| 2242 | if (pimg) | 2417 | if (pimg) |
| 2243 | { | 2418 | { |
| 2244 | #ifdef HAVE_X_WINDOWS | 2419 | #ifdef USE_CAIRO |
| 2245 | xfree (pimg->data); | 2420 | #endif /* USE_CAIRO */ |
| 2246 | pimg->data = NULL; | ||
| 2247 | XDestroyImage (pimg); | ||
| 2248 | #endif /* HAVE_X_WINDOWS */ | ||
| 2249 | #ifdef HAVE_NTGUI | 2421 | #ifdef HAVE_NTGUI |
| 2250 | /* Data will be freed by DestroyObject. */ | 2422 | /* Data will be freed by DestroyObject. */ |
| 2251 | pimg->data = NULL; | 2423 | pimg->data = NULL; |
| @@ -2255,6 +2427,7 @@ image_destroy_x_image (Emacs_Pix_Container pimg) | |||
| 2255 | ns_release_object (pimg); | 2427 | ns_release_object (pimg); |
| 2256 | #endif /* HAVE_NS */ | 2428 | #endif /* HAVE_NS */ |
| 2257 | } | 2429 | } |
| 2430 | #endif | ||
| 2258 | } | 2431 | } |
| 2259 | 2432 | ||
| 2260 | 2433 | ||
| @@ -2266,7 +2439,9 @@ static void | |||
| 2266 | gui_put_x_image (struct frame *f, Emacs_Pix_Container pimg, | 2439 | gui_put_x_image (struct frame *f, Emacs_Pix_Container pimg, |
| 2267 | Emacs_Pixmap pixmap, int width, int height) | 2440 | Emacs_Pixmap pixmap, int width, int height) |
| 2268 | { | 2441 | { |
| 2269 | #ifdef HAVE_X_WINDOWS | 2442 | #ifdef USE_CAIRO |
| 2443 | eassert (pimg == pixmap); | ||
| 2444 | #elif defined HAVE_X_WINDOWS | ||
| 2270 | GC gc; | 2445 | GC gc; |
| 2271 | 2446 | ||
| 2272 | eassert (input_blocked_p ()); | 2447 | eassert (input_blocked_p ()); |
| @@ -2319,7 +2494,7 @@ static void | |||
| 2319 | image_put_x_image (struct frame *f, struct image *img, Emacs_Pix_Container ximg, | 2494 | image_put_x_image (struct frame *f, struct image *img, Emacs_Pix_Container ximg, |
| 2320 | bool mask_p) | 2495 | bool mask_p) |
| 2321 | { | 2496 | { |
| 2322 | #ifdef HAVE_X_WINDOWS | 2497 | #if defined HAVE_X_WINDOWS && !defined USE_CAIRO |
| 2323 | if (!mask_p) | 2498 | if (!mask_p) |
| 2324 | { | 2499 | { |
| 2325 | eassert (img->ximg == NULL); | 2500 | eassert (img->ximg == NULL); |
| @@ -2337,7 +2512,7 @@ image_put_x_image (struct frame *f, struct image *img, Emacs_Pix_Container ximg, | |||
| 2337 | #endif | 2512 | #endif |
| 2338 | } | 2513 | } |
| 2339 | 2514 | ||
| 2340 | #ifdef HAVE_X_WINDOWS | 2515 | #if defined HAVE_X_WINDOWS && !defined USE_CAIRO |
| 2341 | /* Put the X images recorded in IMG on frame F into pixmaps, then free | 2516 | /* Put the X images recorded in IMG on frame F into pixmaps, then free |
| 2342 | the X images and their buffers. */ | 2517 | the X images and their buffers. */ |
| 2343 | 2518 | ||
| @@ -2391,7 +2566,9 @@ image_unget_x_image_or_dc (struct image *img, bool mask_p, | |||
| 2391 | static Emacs_Pix_Container | 2566 | static Emacs_Pix_Container |
| 2392 | image_get_x_image (struct frame *f, struct image *img, bool mask_p) | 2567 | image_get_x_image (struct frame *f, struct image *img, bool mask_p) |
| 2393 | { | 2568 | { |
| 2394 | #ifdef HAVE_X_WINDOWS | 2569 | #ifdef USE_CAIRO |
| 2570 | return !mask_p ? img->pixmap : img->mask; | ||
| 2571 | #elif defined HAVE_X_WINDOWS | ||
| 2395 | XImage *ximg_in_img = !mask_p ? img->ximg : img->mask_img; | 2572 | XImage *ximg_in_img = !mask_p ? img->ximg : img->mask_img; |
| 2396 | 2573 | ||
| 2397 | if (ximg_in_img) | 2574 | if (ximg_in_img) |
| @@ -2410,7 +2587,8 @@ image_get_x_image (struct frame *f, struct image *img, bool mask_p) | |||
| 2410 | static void | 2587 | static void |
| 2411 | image_unget_x_image (struct image *img, bool mask_p, Emacs_Pix_Container ximg) | 2588 | image_unget_x_image (struct image *img, bool mask_p, Emacs_Pix_Container ximg) |
| 2412 | { | 2589 | { |
| 2413 | #ifdef HAVE_X_WINDOWS | 2590 | #ifdef USE_CAIRO |
| 2591 | #elif defined HAVE_X_WINDOWS | ||
| 2414 | XImage *ximg_in_img = !mask_p ? img->ximg : img->mask_img; | 2592 | XImage *ximg_in_img = !mask_p ? img->ximg : img->mask_img; |
| 2415 | 2593 | ||
| 2416 | if (ximg_in_img) | 2594 | if (ximg_in_img) |
| @@ -2869,28 +3047,32 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data, | |||
| 2869 | RGB_PIXEL_COLOR fg, RGB_PIXEL_COLOR bg, | 3047 | RGB_PIXEL_COLOR fg, RGB_PIXEL_COLOR bg, |
| 2870 | bool non_default_colors) | 3048 | bool non_default_colors) |
| 2871 | { | 3049 | { |
| 2872 | #ifdef HAVE_NTGUI | 3050 | #ifdef USE_CAIRO |
| 3051 | Emacs_Color fgbg[] = {{.pixel = fg}, {.pixel = bg}}; | ||
| 3052 | FRAME_TERMINAL (f)->query_colors (f, fgbg, ARRAYELTS (fgbg)); | ||
| 3053 | fg = lookup_rgb_color (f, fgbg[0].red, fgbg[0].green, fgbg[0].blue); | ||
| 3054 | bg = lookup_rgb_color (f, fgbg[1].red, fgbg[1].green, fgbg[1].blue); | ||
| 3055 | img->pixmap | ||
| 3056 | = image_pix_container_create_from_bitmap_data (f, data, img->width, | ||
| 3057 | img->height, fg, bg); | ||
| 3058 | #elif defined HAVE_X_WINDOWS | ||
| 3059 | img->pixmap | ||
| 3060 | = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f), | ||
| 3061 | FRAME_X_DRAWABLE (f), | ||
| 3062 | data, | ||
| 3063 | img->width, img->height, | ||
| 3064 | fg, bg, | ||
| 3065 | DefaultDepthOfScreen (FRAME_X_SCREEN (f))); | ||
| 3066 | #elif defined HAVE_NTGUI | ||
| 2873 | img->pixmap | 3067 | img->pixmap |
| 2874 | = w32_create_pixmap_from_bitmap_data (img->width, img->height, data); | 3068 | = w32_create_pixmap_from_bitmap_data (img->width, img->height, data); |
| 2875 | 3069 | ||
| 2876 | /* If colors were specified, transfer the bitmap to a color one. */ | 3070 | /* If colors were specified, transfer the bitmap to a color one. */ |
| 2877 | if (non_default_colors) | 3071 | if (non_default_colors) |
| 2878 | convert_mono_to_color_image (f, img, fg, bg); | 3072 | convert_mono_to_color_image (f, img, fg, bg); |
| 2879 | 3073 | #elif defined HAVE_NS | |
| 2880 | #elif defined (HAVE_NS) | ||
| 2881 | img->pixmap = ns_image_from_XBM (data, img->width, img->height, fg, bg); | 3074 | img->pixmap = ns_image_from_XBM (data, img->width, img->height, fg, bg); |
| 2882 | 3075 | #endif | |
| 2883 | #else | ||
| 2884 | img->pixmap = | ||
| 2885 | (image_check_image_size (0, img->width, img->height) | ||
| 2886 | ? XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f), | ||
| 2887 | FRAME_X_DRAWABLE (f), | ||
| 2888 | data, | ||
| 2889 | img->width, img->height, | ||
| 2890 | fg, bg, | ||
| 2891 | DefaultDepthOfScreen (FRAME_X_SCREEN (f))) | ||
| 2892 | : NO_PIXMAP); | ||
| 2893 | #endif /* !HAVE_NTGUI && !HAVE_NS */ | ||
| 2894 | } | 3076 | } |
| 2895 | 3077 | ||
| 2896 | 3078 | ||
| @@ -3099,9 +3281,12 @@ xbm_load_image (struct frame *f, struct image *img, char *contents, char *end) | |||
| 3099 | non_default_colors = 1; | 3281 | non_default_colors = 1; |
| 3100 | } | 3282 | } |
| 3101 | 3283 | ||
| 3102 | Create_Pixmap_From_Bitmap_Data (f, img, data, | 3284 | if (image_check_image_size (0, img->width, img->height)) |
| 3103 | foreground, background, | 3285 | Create_Pixmap_From_Bitmap_Data (f, img, data, |
| 3104 | non_default_colors); | 3286 | foreground, background, |
| 3287 | non_default_colors); | ||
| 3288 | else | ||
| 3289 | img->pixmap = NO_PIXMAP; | ||
| 3105 | xfree (data); | 3290 | xfree (data); |
| 3106 | 3291 | ||
| 3107 | if (img->pixmap == NO_PIXMAP) | 3292 | if (img->pixmap == NO_PIXMAP) |
| @@ -3315,7 +3500,7 @@ xbm_load (struct frame *f, struct image *img) | |||
| 3315 | #endif /* not HAVE_NTGUI */ | 3500 | #endif /* not HAVE_NTGUI */ |
| 3316 | #endif /* HAVE_XPM */ | 3501 | #endif /* HAVE_XPM */ |
| 3317 | 3502 | ||
| 3318 | #if defined (HAVE_XPM) || defined (HAVE_NS) | 3503 | #if defined HAVE_XPM || defined USE_CAIRO || defined HAVE_NS |
| 3319 | 3504 | ||
| 3320 | /* Indices of image specification fields in xpm_format, below. */ | 3505 | /* Indices of image specification fields in xpm_format, below. */ |
| 3321 | 3506 | ||
| @@ -3353,19 +3538,17 @@ static const struct image_keyword xpm_format[XPM_LAST] = | |||
| 3353 | {":background", IMAGE_STRING_OR_NIL_VALUE, 0} | 3538 | {":background", IMAGE_STRING_OR_NIL_VALUE, 0} |
| 3354 | }; | 3539 | }; |
| 3355 | 3540 | ||
| 3356 | #ifdef HAVE_X_WINDOWS | 3541 | #if defined HAVE_X_WINDOWS && !defined USE_CAIRO |
| 3357 | 3542 | ||
| 3358 | /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation | 3543 | /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation |
| 3359 | functions for allocating image colors. Our own functions handle | 3544 | functions for allocating image colors. Our own functions handle |
| 3360 | color allocation failures more gracefully than the ones on the XPM | 3545 | color allocation failures more gracefully than the ones on the XPM |
| 3361 | lib. */ | 3546 | lib. */ |
| 3362 | 3547 | ||
| 3363 | #ifndef USE_CAIRO | ||
| 3364 | #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure | 3548 | #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure |
| 3365 | #define ALLOC_XPM_COLORS | 3549 | #define ALLOC_XPM_COLORS |
| 3366 | #endif | 3550 | #endif |
| 3367 | #endif /* USE_CAIRO */ | 3551 | #endif /* HAVE_X_WINDOWS && !USE_CAIRO */ |
| 3368 | #endif /* HAVE_X_WINDOWS */ | ||
| 3369 | 3552 | ||
| 3370 | #ifdef ALLOC_XPM_COLORS | 3553 | #ifdef ALLOC_XPM_COLORS |
| 3371 | 3554 | ||
| @@ -3614,7 +3797,7 @@ xpm_image_p (Lisp_Object object) | |||
| 3614 | || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))); | 3797 | || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))); |
| 3615 | } | 3798 | } |
| 3616 | 3799 | ||
| 3617 | #endif /* HAVE_XPM || HAVE_NS */ | 3800 | #endif /* HAVE_XPM || USE_CAIRO || HAVE_NS */ |
| 3618 | 3801 | ||
| 3619 | #if defined HAVE_XPM && defined HAVE_X_WINDOWS && !defined USE_GTK | 3802 | #if defined HAVE_XPM && defined HAVE_X_WINDOWS && !defined USE_GTK |
| 3620 | ptrdiff_t | 3803 | ptrdiff_t |
| @@ -3670,7 +3853,7 @@ x_create_bitmap_from_xpm_data (struct frame *f, const char **bits) | |||
| 3670 | /* Load image IMG which will be displayed on frame F. Value is | 3853 | /* Load image IMG which will be displayed on frame F. Value is |
| 3671 | true if successful. */ | 3854 | true if successful. */ |
| 3672 | 3855 | ||
| 3673 | #ifdef HAVE_XPM | 3856 | #if defined HAVE_XPM && !defined USE_CAIRO |
| 3674 | 3857 | ||
| 3675 | static bool | 3858 | static bool |
| 3676 | xpm_load (struct frame *f, struct image *img) | 3859 | xpm_load (struct frame *f, struct image *img) |
| @@ -3838,44 +4021,6 @@ xpm_load (struct frame *f, struct image *img) | |||
| 3838 | #endif /* HAVE_NTGUI */ | 4021 | #endif /* HAVE_NTGUI */ |
| 3839 | } | 4022 | } |
| 3840 | 4023 | ||
| 3841 | #ifdef USE_CAIRO | ||
| 3842 | /* Load very specific Xpm:s. */ | ||
| 3843 | if (rc == XpmSuccess | ||
| 3844 | && img->ximg->format == ZPixmap | ||
| 3845 | && img->ximg->bits_per_pixel == 32 | ||
| 3846 | && (! img->mask_img || img->mask_img->bits_per_pixel == 1)) | ||
| 3847 | { | ||
| 3848 | int width = img->ximg->width; | ||
| 3849 | int height = img->ximg->height; | ||
| 3850 | cairo_surface_t *surface = create_cairo_image_surface (width, height); | ||
| 3851 | int i; | ||
| 3852 | uint32_t *od = (uint32_t *) cairo_image_surface_get_data (surface); | ||
| 3853 | uint32_t *id = (uint32_t *) img->ximg->data; | ||
| 3854 | char *mid = img->mask_img ? img->mask_img->data : 0; | ||
| 3855 | uint32_t bgcolor = get_spec_bg_or_alpha_as_argb (img, f); | ||
| 3856 | |||
| 3857 | for (i = 0; i < height; ++i) | ||
| 3858 | { | ||
| 3859 | int k; | ||
| 3860 | for (k = 0; k < width; ++k) | ||
| 3861 | { | ||
| 3862 | int idx = i * img->ximg->bytes_per_line/4 + k; | ||
| 3863 | int maskidx = mid ? i * img->mask_img->bytes_per_line + k/8 : 0; | ||
| 3864 | int mask = mid ? mid[maskidx] & (1 << (k % 8)) : 1; | ||
| 3865 | |||
| 3866 | if (mask) od[idx] = id[idx] + 0xff000000; /* ff => full alpha */ | ||
| 3867 | else od[idx] = bgcolor; | ||
| 3868 | } | ||
| 3869 | } | ||
| 3870 | |||
| 3871 | set_cairo_image_surface (img, surface); | ||
| 3872 | } | ||
| 3873 | else | ||
| 3874 | { | ||
| 3875 | rc = XpmFileInvalid; | ||
| 3876 | image_clear_image (f, img); | ||
| 3877 | } | ||
| 3878 | #else | ||
| 3879 | #ifdef HAVE_X_WINDOWS | 4024 | #ifdef HAVE_X_WINDOWS |
| 3880 | if (rc == XpmSuccess) | 4025 | if (rc == XpmSuccess) |
| 3881 | { | 4026 | { |
| @@ -3901,7 +4046,6 @@ xpm_load (struct frame *f, struct image *img) | |||
| 3901 | } | 4046 | } |
| 3902 | } | 4047 | } |
| 3903 | #endif | 4048 | #endif |
| 3904 | #endif /* ! USE_CAIRO */ | ||
| 3905 | 4049 | ||
| 3906 | if (rc == XpmSuccess) | 4050 | if (rc == XpmSuccess) |
| 3907 | { | 4051 | { |
| @@ -4004,9 +4148,9 @@ xpm_load (struct frame *f, struct image *img) | |||
| 4004 | return rc == XpmSuccess; | 4148 | return rc == XpmSuccess; |
| 4005 | } | 4149 | } |
| 4006 | 4150 | ||
| 4007 | #endif /* HAVE_XPM */ | 4151 | #endif /* HAVE_XPM && !USE_CAIRO */ |
| 4008 | 4152 | ||
| 4009 | #if defined (HAVE_NS) && !defined (HAVE_XPM) | 4153 | #if defined USE_CAIRO || (defined HAVE_NS && !defined HAVE_XPM) |
| 4010 | 4154 | ||
| 4011 | /* XPM support functions for NS where libxpm is not available. | 4155 | /* XPM support functions for NS where libxpm is not available. |
| 4012 | Only XPM version 3 (without any extensions) is supported. */ | 4156 | Only XPM version 3 (without any extensions) is supported. */ |
| @@ -4346,7 +4490,9 @@ xpm_load_image (struct frame *f, | |||
| 4346 | color_val = Qt; | 4490 | color_val = Qt; |
| 4347 | else if (FRAME_TERMINAL (f)->defined_color_hook | 4491 | else if (FRAME_TERMINAL (f)->defined_color_hook |
| 4348 | (f, SSDATA (XCDR (specified_color)), &cdef, false, false)) | 4492 | (f, SSDATA (XCDR (specified_color)), &cdef, false, false)) |
| 4349 | color_val = make_fixnum (cdef.pixel); | 4493 | color_val |
| 4494 | = make_fixnum (lookup_rgb_color (f, cdef.red, cdef.green, | ||
| 4495 | cdef.blue)); | ||
| 4350 | } | 4496 | } |
| 4351 | } | 4497 | } |
| 4352 | if (NILP (color_val) && max_key > 0) | 4498 | if (NILP (color_val) && max_key > 0) |
| @@ -4355,7 +4501,8 @@ xpm_load_image (struct frame *f, | |||
| 4355 | color_val = Qt; | 4501 | color_val = Qt; |
| 4356 | else if (FRAME_TERMINAL (f)->defined_color_hook | 4502 | else if (FRAME_TERMINAL (f)->defined_color_hook |
| 4357 | (f, max_color, &cdef, false, false)) | 4503 | (f, max_color, &cdef, false, false)) |
| 4358 | color_val = make_fixnum (cdef.pixel); | 4504 | color_val = make_fixnum (lookup_rgb_color (f, cdef.red, cdef.green, |
| 4505 | cdef.blue)); | ||
| 4359 | } | 4506 | } |
| 4360 | if (!NILP (color_val)) | 4507 | if (!NILP (color_val)) |
| 4361 | (*put_color_table) (color_table, beg, chars_per_pixel, color_val); | 4508 | (*put_color_table) (color_table, beg, chars_per_pixel, color_val); |
| @@ -4363,6 +4510,14 @@ xpm_load_image (struct frame *f, | |||
| 4363 | expect (','); | 4510 | expect (','); |
| 4364 | } | 4511 | } |
| 4365 | 4512 | ||
| 4513 | unsigned long frame_fg = FRAME_FOREGROUND_PIXEL (f); | ||
| 4514 | #ifdef USE_CAIRO | ||
| 4515 | { | ||
| 4516 | Emacs_Color color = {.pixel = frame_fg}; | ||
| 4517 | FRAME_TERMINAL (f)->query_colors (f, &color, 1); | ||
| 4518 | frame_fg = lookup_rgb_color (f, color.red, color.green, color.blue); | ||
| 4519 | } | ||
| 4520 | #endif | ||
| 4366 | for (y = 0; y < height; y++) | 4521 | for (y = 0; y < height; y++) |
| 4367 | { | 4522 | { |
| 4368 | expect (XPM_TK_STRING); | 4523 | expect (XPM_TK_STRING); |
| @@ -4374,11 +4529,10 @@ xpm_load_image (struct frame *f, | |||
| 4374 | Lisp_Object color_val = | 4529 | Lisp_Object color_val = |
| 4375 | (*get_color_table) (color_table, str, chars_per_pixel); | 4530 | (*get_color_table) (color_table, str, chars_per_pixel); |
| 4376 | 4531 | ||
| 4377 | XPutPixel (ximg, x, y, | 4532 | PUT_PIXEL (ximg, x, y, |
| 4378 | (FIXNUMP (color_val) ? XFIXNUM (color_val) | 4533 | FIXNUMP (color_val) ? XFIXNUM (color_val) : frame_fg); |
| 4379 | : FRAME_FOREGROUND_PIXEL (f))); | ||
| 4380 | #ifndef HAVE_NS | 4534 | #ifndef HAVE_NS |
| 4381 | XPutPixel (mask_img, x, y, | 4535 | PUT_PIXEL (mask_img, x, y, |
| 4382 | (!EQ (color_val, Qt) ? PIX_MASK_DRAW | 4536 | (!EQ (color_val, Qt) ? PIX_MASK_DRAW |
| 4383 | : (have_mask = true, PIX_MASK_RETAIN))); | 4537 | : (have_mask = true, PIX_MASK_RETAIN))); |
| 4384 | #else | 4538 | #else |
| @@ -4735,10 +4889,8 @@ lookup_rgb_color (struct frame *f, int r, int g, int b) | |||
| 4735 | { | 4889 | { |
| 4736 | #ifdef HAVE_NTGUI | 4890 | #ifdef HAVE_NTGUI |
| 4737 | return PALETTERGB (r >> 8, g >> 8, b >> 8); | 4891 | return PALETTERGB (r >> 8, g >> 8, b >> 8); |
| 4738 | #elif defined HAVE_NS | 4892 | #elif defined USE_CAIRO || defined HAVE_NS |
| 4739 | return RGB_TO_ULONG (r >> 8, g >> 8, b >> 8); | 4893 | return RGB_TO_ULONG (r >> 8, g >> 8, b >> 8); |
| 4740 | #elif defined USE_CAIRO | ||
| 4741 | return (0xffu << 24) | (r << 16) | (g << 8) | b; | ||
| 4742 | #else | 4894 | #else |
| 4743 | xsignal1 (Qfile_error, | 4895 | xsignal1 (Qfile_error, |
| 4744 | build_string ("This Emacs mishandles this image file type")); | 4896 | build_string ("This Emacs mishandles this image file type")); |
| @@ -4810,7 +4962,7 @@ image_to_emacs_colors (struct frame *f, struct image *img, bool rgb_p) | |||
| 4810 | p = colors; | 4962 | p = colors; |
| 4811 | for (y = 0; y < img->height; ++y) | 4963 | for (y = 0; y < img->height; ++y) |
| 4812 | { | 4964 | { |
| 4813 | #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) | 4965 | #if !defined USE_CAIRO && !defined HAVE_NS |
| 4814 | Emacs_Color *row = p; | 4966 | Emacs_Color *row = p; |
| 4815 | for (x = 0; x < img->width; ++x, ++p) | 4967 | for (x = 0; x < img->width; ++x, ++p) |
| 4816 | p->pixel = GET_PIXEL (ximg, x, y); | 4968 | p->pixel = GET_PIXEL (ximg, x, y); |
| @@ -4818,11 +4970,9 @@ image_to_emacs_colors (struct frame *f, struct image *img, bool rgb_p) | |||
| 4818 | { | 4970 | { |
| 4819 | FRAME_TERMINAL (f)->query_colors (f, row, img->width); | 4971 | FRAME_TERMINAL (f)->query_colors (f, row, img->width); |
| 4820 | } | 4972 | } |
| 4821 | #else | 4973 | #else /* USE_CAIRO || HAVE_NS */ |
| 4822 | |||
| 4823 | for (x = 0; x < img->width; ++x, ++p) | 4974 | for (x = 0; x < img->width; ++x, ++p) |
| 4824 | { | 4975 | { |
| 4825 | /* W32_TODO: palette support needed here? */ | ||
| 4826 | p->pixel = GET_PIXEL (ximg, x, y); | 4976 | p->pixel = GET_PIXEL (ximg, x, y); |
| 4827 | if (rgb_p) | 4977 | if (rgb_p) |
| 4828 | { | 4978 | { |
| @@ -4831,7 +4981,7 @@ image_to_emacs_colors (struct frame *f, struct image *img, bool rgb_p) | |||
| 4831 | p->blue = BLUE16_FROM_ULONG (p->pixel); | 4981 | p->blue = BLUE16_FROM_ULONG (p->pixel); |
| 4832 | } | 4982 | } |
| 4833 | } | 4983 | } |
| 4834 | #endif /* HAVE_X_WINDOWS */ | 4984 | #endif /* USE_CAIRO || HAVE_NS */ |
| 4835 | } | 4985 | } |
| 4836 | 4986 | ||
| 4837 | image_unget_x_image_or_dc (img, 0, ximg, prev); | 4987 | image_unget_x_image_or_dc (img, 0, ximg, prev); |
| @@ -4907,7 +5057,7 @@ image_from_emacs_colors (struct frame *f, struct image *img, Emacs_Color *colors | |||
| 4907 | { | 5057 | { |
| 4908 | unsigned long pixel; | 5058 | unsigned long pixel; |
| 4909 | pixel = lookup_rgb_color (f, p->red, p->green, p->blue); | 5059 | pixel = lookup_rgb_color (f, p->red, p->green, p->blue); |
| 4910 | XPutPixel (oimg, x, y, pixel); | 5060 | PUT_PIXEL (oimg, x, y, pixel); |
| 4911 | } | 5061 | } |
| 4912 | 5062 | ||
| 4913 | xfree (colors); | 5063 | xfree (colors); |
| @@ -5056,6 +5206,44 @@ image_edge_detection (struct frame *f, struct image *img, | |||
| 5056 | } | 5206 | } |
| 5057 | 5207 | ||
| 5058 | 5208 | ||
| 5209 | #if defined HAVE_X_WINDOWS || defined USE_CAIRO | ||
| 5210 | static void | ||
| 5211 | image_pixmap_draw_cross (struct frame *f, Emacs_Pixmap pixmap, | ||
| 5212 | int x, int y, unsigned int width, unsigned int height, | ||
| 5213 | unsigned long color) | ||
| 5214 | { | ||
| 5215 | #ifdef USE_CAIRO | ||
| 5216 | cairo_surface_t *surface | ||
| 5217 | = cairo_image_surface_create_for_data ((unsigned char *) pixmap->data, | ||
| 5218 | (pixmap->bits_per_pixel == 32 | ||
| 5219 | ? CAIRO_FORMAT_RGB24 | ||
| 5220 | : CAIRO_FORMAT_A8), | ||
| 5221 | pixmap->width, pixmap->height, | ||
| 5222 | pixmap->bytes_per_line); | ||
| 5223 | cairo_t *cr = cairo_create (surface); | ||
| 5224 | cairo_surface_destroy (surface); | ||
| 5225 | cairo_set_source_rgb (cr, RED_FROM_ULONG (color) / 255.0, | ||
| 5226 | GREEN_FROM_ULONG (color) / 255.0, | ||
| 5227 | BLUE_FROM_ULONG (color) / 255.0); | ||
| 5228 | cairo_move_to (cr, x + 0.5, y + 0.5); | ||
| 5229 | cairo_rel_line_to (cr, width - 1, height - 1); | ||
| 5230 | cairo_rel_move_to (cr, 0, - (height - 1)); | ||
| 5231 | cairo_rel_line_to (cr, - (width - 1), height - 1); | ||
| 5232 | cairo_set_line_width (cr, 1); | ||
| 5233 | cairo_stroke (cr); | ||
| 5234 | cairo_destroy (cr); | ||
| 5235 | #elif HAVE_X_WINDOWS | ||
| 5236 | Display *dpy = FRAME_X_DISPLAY (f); | ||
| 5237 | GC gc = XCreateGC (dpy, pixmap, 0, NULL); | ||
| 5238 | |||
| 5239 | XSetForeground (dpy, gc, color); | ||
| 5240 | XDrawLine (dpy, pixmap, gc, x, y, x + width - 1, y + height - 1); | ||
| 5241 | XDrawLine (dpy, pixmap, gc, x, y + height - 1, x + width - 1, y); | ||
| 5242 | XFreeGC (dpy, gc); | ||
| 5243 | #endif /* HAVE_X_WINDOWS */ | ||
| 5244 | } | ||
| 5245 | #endif /* HAVE_X_WINDOWS || USE_CAIRO */ | ||
| 5246 | |||
| 5059 | /* Transform image IMG on frame F so that it looks disabled. */ | 5247 | /* Transform image IMG on frame F so that it looks disabled. */ |
| 5060 | 5248 | ||
| 5061 | static void | 5249 | static void |
| @@ -5097,30 +5285,22 @@ image_disable_image (struct frame *f, struct image *img) | |||
| 5097 | #ifndef HAVE_NTGUI | 5285 | #ifndef HAVE_NTGUI |
| 5098 | #ifndef HAVE_NS /* TODO: NS support, however this not needed for toolbars */ | 5286 | #ifndef HAVE_NS /* TODO: NS support, however this not needed for toolbars */ |
| 5099 | 5287 | ||
| 5288 | #ifndef USE_CAIRO | ||
| 5289 | #define CrossForeground(f) BLACK_PIX_DEFAULT (f) | ||
| 5100 | #define MaskForeground(f) WHITE_PIX_DEFAULT (f) | 5290 | #define MaskForeground(f) WHITE_PIX_DEFAULT (f) |
| 5291 | #else /* USE_CAIRO */ | ||
| 5292 | #define CrossForeground(f) 0 | ||
| 5293 | #define MaskForeground(f) PIX_MASK_DRAW | ||
| 5294 | #endif /* USE_CAIRO */ | ||
| 5101 | 5295 | ||
| 5102 | Display *dpy = FRAME_X_DISPLAY (f); | 5296 | #ifndef USE_CAIRO |
| 5103 | GC gc; | ||
| 5104 | |||
| 5105 | image_sync_to_pixmaps (f, img); | 5297 | image_sync_to_pixmaps (f, img); |
| 5106 | gc = XCreateGC (dpy, img->pixmap, 0, NULL); | 5298 | #endif /* !USE_CAIRO */ |
| 5107 | XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f)); | 5299 | image_pixmap_draw_cross (f, img->pixmap, 0, 0, img->width, img->height, |
| 5108 | XDrawLine (dpy, img->pixmap, gc, 0, 0, | 5300 | CrossForeground (f)); |
| 5109 | img->width - 1, img->height - 1); | ||
| 5110 | XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1, | ||
| 5111 | img->width - 1, 0); | ||
| 5112 | XFreeGC (dpy, gc); | ||
| 5113 | |||
| 5114 | if (img->mask) | 5301 | if (img->mask) |
| 5115 | { | 5302 | image_pixmap_draw_cross (f, img->mask, 0, 0, img->width, img->height, |
| 5116 | gc = XCreateGC (dpy, img->mask, 0, NULL); | 5303 | MaskForeground (f)); |
| 5117 | XSetForeground (dpy, gc, MaskForeground (f)); | ||
| 5118 | XDrawLine (dpy, img->mask, gc, 0, 0, | ||
| 5119 | img->width - 1, img->height - 1); | ||
| 5120 | XDrawLine (dpy, img->mask, gc, 0, img->height - 1, | ||
| 5121 | img->width - 1, 0); | ||
| 5122 | XFreeGC (dpy, gc); | ||
| 5123 | } | ||
| 5124 | #endif /* !HAVE_NS */ | 5304 | #endif /* !HAVE_NS */ |
| 5125 | #else | 5305 | #else |
| 5126 | HDC hdc, bmpdc; | 5306 | HDC hdc, bmpdc; |
| @@ -5212,6 +5392,7 @@ image_build_heuristic_mask (struct frame *f, struct image *img, | |||
| 5212 | 5392 | ||
| 5213 | if (i == 3 && NILP (how)) | 5393 | if (i == 3 && NILP (how)) |
| 5214 | { | 5394 | { |
| 5395 | #ifndef USE_CAIRO | ||
| 5215 | char color_name[30]; | 5396 | char color_name[30]; |
| 5216 | sprintf (color_name, "#%04x%04x%04x", | 5397 | sprintf (color_name, "#%04x%04x%04x", |
| 5217 | rgb[0] + 0u, rgb[1] + 0u, rgb[2] + 0u); | 5398 | rgb[0] + 0u, rgb[1] + 0u, rgb[2] + 0u); |
| @@ -5220,6 +5401,9 @@ image_build_heuristic_mask (struct frame *f, struct image *img, | |||
| 5220 | 0x00ffffff & /* Filter out palette info. */ | 5401 | 0x00ffffff & /* Filter out palette info. */ |
| 5221 | #endif /* HAVE_NTGUI */ | 5402 | #endif /* HAVE_NTGUI */ |
| 5222 | image_alloc_image_color (f, img, build_string (color_name), 0)); | 5403 | image_alloc_image_color (f, img, build_string (color_name), 0)); |
| 5404 | #else /* USE_CAIRO */ | ||
| 5405 | bg = lookup_rgb_color (f, rgb[0], rgb[1], rgb[2]); | ||
| 5406 | #endif /* USE_CAIRO */ | ||
| 5223 | use_img_background = 0; | 5407 | use_img_background = 0; |
| 5224 | } | 5408 | } |
| 5225 | } | 5409 | } |
| @@ -5233,7 +5417,7 @@ image_build_heuristic_mask (struct frame *f, struct image *img, | |||
| 5233 | for (y = 0; y < img->height; ++y) | 5417 | for (y = 0; y < img->height; ++y) |
| 5234 | for (x = 0; x < img->width; ++x) | 5418 | for (x = 0; x < img->width; ++x) |
| 5235 | #ifndef HAVE_NS | 5419 | #ifndef HAVE_NS |
| 5236 | XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg | 5420 | PUT_PIXEL (mask_img, x, y, (GET_PIXEL (ximg, x, y) != bg |
| 5237 | ? PIX_MASK_DRAW : PIX_MASK_RETAIN)); | 5421 | ? PIX_MASK_DRAW : PIX_MASK_RETAIN)); |
| 5238 | #else | 5422 | #else |
| 5239 | if (XGetPixel (ximg, x, y) == bg) | 5423 | if (XGetPixel (ximg, x, y) == bg) |
| @@ -5406,9 +5590,7 @@ pbm_load (struct frame *f, struct image *img) | |||
| 5406 | enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type; | 5590 | enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type; |
| 5407 | char *contents = NULL; | 5591 | char *contents = NULL; |
| 5408 | char *end, *p; | 5592 | char *end, *p; |
| 5409 | #ifndef USE_CAIRO | ||
| 5410 | Emacs_Pix_Container ximg; | 5593 | Emacs_Pix_Container ximg; |
| 5411 | #endif | ||
| 5412 | 5594 | ||
| 5413 | specified_file = image_spec_value (img->spec, QCfile, NULL); | 5595 | specified_file = image_spec_value (img->spec, QCfile, NULL); |
| 5414 | 5596 | ||
| @@ -5492,11 +5674,6 @@ pbm_load (struct frame *f, struct image *img) | |||
| 5492 | width = pbm_scan_number (&p, end); | 5674 | width = pbm_scan_number (&p, end); |
| 5493 | height = pbm_scan_number (&p, end); | 5675 | height = pbm_scan_number (&p, end); |
| 5494 | 5676 | ||
| 5495 | #ifdef USE_CAIRO | ||
| 5496 | cairo_surface_t *surface = create_cairo_image_surface (width, height); | ||
| 5497 | uint32_t *dataptr = (uint32_t *) cairo_image_surface_get_data (surface); | ||
| 5498 | #endif | ||
| 5499 | |||
| 5500 | if (type != PBM_MONO) | 5677 | if (type != PBM_MONO) |
| 5501 | { | 5678 | { |
| 5502 | max_color_idx = pbm_scan_number (&p, end); | 5679 | max_color_idx = pbm_scan_number (&p, end); |
| @@ -5513,10 +5690,8 @@ pbm_load (struct frame *f, struct image *img) | |||
| 5513 | goto error; | 5690 | goto error; |
| 5514 | } | 5691 | } |
| 5515 | 5692 | ||
| 5516 | #ifndef USE_CAIRO | ||
| 5517 | if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) | 5693 | if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) |
| 5518 | goto error; | 5694 | goto error; |
| 5519 | #endif | ||
| 5520 | 5695 | ||
| 5521 | /* Initialize the color hash table. */ | 5696 | /* Initialize the color hash table. */ |
| 5522 | init_color_table (); | 5697 | init_color_table (); |
| @@ -5528,42 +5703,11 @@ pbm_load (struct frame *f, struct image *img) | |||
| 5528 | struct image_keyword fmt[PBM_LAST]; | 5703 | struct image_keyword fmt[PBM_LAST]; |
| 5529 | unsigned long fg = FRAME_FOREGROUND_PIXEL (f); | 5704 | unsigned long fg = FRAME_FOREGROUND_PIXEL (f); |
| 5530 | unsigned long bg = FRAME_BACKGROUND_PIXEL (f); | 5705 | unsigned long bg = FRAME_BACKGROUND_PIXEL (f); |
| 5531 | #ifdef USE_CAIRO | ||
| 5532 | Emacs_Color xfg, xbg; | ||
| 5533 | int fga32, bga32; | ||
| 5534 | #endif | ||
| 5535 | /* Parse the image specification. */ | 5706 | /* Parse the image specification. */ |
| 5536 | memcpy (fmt, pbm_format, sizeof fmt); | 5707 | memcpy (fmt, pbm_format, sizeof fmt); |
| 5537 | parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm); | 5708 | parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm); |
| 5538 | 5709 | ||
| 5539 | /* Get foreground and background colors, maybe allocate colors. */ | 5710 | /* Get foreground and background colors, maybe allocate colors. */ |
| 5540 | #ifdef USE_CAIRO | ||
| 5541 | if (! fmt[PBM_FOREGROUND].count | ||
| 5542 | || ! STRINGP (fmt[PBM_FOREGROUND].value) | ||
| 5543 | || ! FRAME_TERMINAL (f)->defined_color_hook (f, | ||
| 5544 | SSDATA (fmt[PBM_FOREGROUND].value), | ||
| 5545 | &xfg, | ||
| 5546 | false, | ||
| 5547 | false)) | ||
| 5548 | { | ||
| 5549 | xfg.pixel = fg; | ||
| 5550 | x_query_colors (f, &xfg, 1); | ||
| 5551 | } | ||
| 5552 | fga32 = emacs_color_to_argb32 (&xfg); | ||
| 5553 | |||
| 5554 | if (! fmt[PBM_BACKGROUND].count | ||
| 5555 | || ! STRINGP (fmt[PBM_BACKGROUND].value) | ||
| 5556 | || ! FRAME_TERMINAL (f)->defined_color_hook (f, | ||
| 5557 | SSDATA (fmt[PBM_BACKGROUND].value), | ||
| 5558 | &xbg, | ||
| 5559 | false, | ||
| 5560 | false)) | ||
| 5561 | { | ||
| 5562 | xbg.pixel = bg; | ||
| 5563 | x_query_colors (f, &xbg, 1); | ||
| 5564 | } | ||
| 5565 | bga32 = emacs_color_to_argb32 (&xbg); | ||
| 5566 | #else | ||
| 5567 | if (fmt[PBM_FOREGROUND].count | 5711 | if (fmt[PBM_FOREGROUND].count |
| 5568 | && STRINGP (fmt[PBM_FOREGROUND].value)) | 5712 | && STRINGP (fmt[PBM_FOREGROUND].value)) |
| 5569 | fg = image_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg); | 5713 | fg = image_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg); |
| @@ -5574,8 +5718,15 @@ pbm_load (struct frame *f, struct image *img) | |||
| 5574 | img->background = bg; | 5718 | img->background = bg; |
| 5575 | img->background_valid = 1; | 5719 | img->background_valid = 1; |
| 5576 | } | 5720 | } |
| 5577 | #endif | ||
| 5578 | 5721 | ||
| 5722 | #ifdef USE_CAIRO | ||
| 5723 | { | ||
| 5724 | Emacs_Color fgbg[] = {{.pixel = fg}, {.pixel = bg}}; | ||
| 5725 | FRAME_TERMINAL (f)->query_colors (f, fgbg, ARRAYELTS (fgbg)); | ||
| 5726 | fg = lookup_rgb_color (f, fgbg[0].red, fgbg[0].green, fgbg[0].blue); | ||
| 5727 | bg = lookup_rgb_color (f, fgbg[1].red, fgbg[1].green, fgbg[1].blue); | ||
| 5728 | } | ||
| 5729 | #endif | ||
| 5579 | for (y = 0; y < height; ++y) | 5730 | for (y = 0; y < height; ++y) |
| 5580 | for (x = 0; x < width; ++x) | 5731 | for (x = 0; x < width; ++x) |
| 5581 | { | 5732 | { |
| @@ -5585,11 +5736,7 @@ pbm_load (struct frame *f, struct image *img) | |||
| 5585 | { | 5736 | { |
| 5586 | if (p >= end) | 5737 | if (p >= end) |
| 5587 | { | 5738 | { |
| 5588 | #ifdef USE_CAIRO | ||
| 5589 | cairo_surface_destroy (surface); | ||
| 5590 | #else | ||
| 5591 | image_destroy_x_image (ximg); | 5739 | image_destroy_x_image (ximg); |
| 5592 | #endif | ||
| 5593 | image_clear_image (f, img); | 5740 | image_clear_image (f, img); |
| 5594 | image_error ("Invalid image size in image `%s'", | 5741 | image_error ("Invalid image size in image `%s'", |
| 5595 | img->spec); | 5742 | img->spec); |
| @@ -5613,11 +5760,7 @@ pbm_load (struct frame *f, struct image *img) | |||
| 5613 | g = 0; | 5760 | g = 0; |
| 5614 | } | 5761 | } |
| 5615 | 5762 | ||
| 5616 | #ifdef USE_CAIRO | 5763 | PUT_PIXEL (ximg, x, y, g ? fg : bg); |
| 5617 | *dataptr++ = g ? fga32 : bga32; | ||
| 5618 | #else | ||
| 5619 | XPutPixel (ximg, x, y, g ? fg : bg); | ||
| 5620 | #endif | ||
| 5621 | } | 5764 | } |
| 5622 | } | 5765 | } |
| 5623 | else | 5766 | else |
| @@ -5631,11 +5774,7 @@ pbm_load (struct frame *f, struct image *img) | |||
| 5631 | 5774 | ||
| 5632 | if (raw_p && p + expected_size > end) | 5775 | if (raw_p && p + expected_size > end) |
| 5633 | { | 5776 | { |
| 5634 | #ifdef USE_CAIRO | ||
| 5635 | cairo_surface_destroy (surface); | ||
| 5636 | #else | ||
| 5637 | image_destroy_x_image (ximg); | 5777 | image_destroy_x_image (ximg); |
| 5638 | #endif | ||
| 5639 | image_clear_image (f, img); | 5778 | image_clear_image (f, img); |
| 5640 | image_error ("Invalid image size in image `%s'", img->spec); | 5779 | image_error ("Invalid image size in image `%s'", img->spec); |
| 5641 | goto error; | 5780 | goto error; |
| @@ -5665,28 +5804,17 @@ pbm_load (struct frame *f, struct image *img) | |||
| 5665 | 5804 | ||
| 5666 | if (r < 0 || g < 0 || b < 0) | 5805 | if (r < 0 || g < 0 || b < 0) |
| 5667 | { | 5806 | { |
| 5668 | #ifdef USE_CAIRO | ||
| 5669 | cairo_surface_destroy (surface); | ||
| 5670 | #else | ||
| 5671 | image_destroy_x_image (ximg); | 5807 | image_destroy_x_image (ximg); |
| 5672 | #endif | ||
| 5673 | image_error ("Invalid pixel value in image `%s'", img->spec); | 5808 | image_error ("Invalid pixel value in image `%s'", img->spec); |
| 5674 | goto error; | 5809 | goto error; |
| 5675 | } | 5810 | } |
| 5676 | 5811 | ||
| 5677 | #ifdef USE_CAIRO | ||
| 5678 | r = (double) r * 255 / max_color_idx; | ||
| 5679 | g = (double) g * 255 / max_color_idx; | ||
| 5680 | b = (double) b * 255 / max_color_idx; | ||
| 5681 | *dataptr++ = (0xffu << 24) | (r << 16) | (g << 8) | b; | ||
| 5682 | #else | ||
| 5683 | /* RGB values are now in the range 0..max_color_idx. | 5812 | /* RGB values are now in the range 0..max_color_idx. |
| 5684 | Scale this to the range 0..0xffff supported by X. */ | 5813 | Scale this to the range 0..0xffff supported by X. */ |
| 5685 | r = (double) r * 65535 / max_color_idx; | 5814 | r = (double) r * 65535 / max_color_idx; |
| 5686 | g = (double) g * 65535 / max_color_idx; | 5815 | g = (double) g * 65535 / max_color_idx; |
| 5687 | b = (double) b * 65535 / max_color_idx; | 5816 | b = (double) b * 65535 / max_color_idx; |
| 5688 | XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b)); | 5817 | PUT_PIXEL (ximg, x, y, lookup_rgb_color (f, r, g, b)); |
| 5689 | #endif | ||
| 5690 | } | 5818 | } |
| 5691 | } | 5819 | } |
| 5692 | 5820 | ||
| @@ -5702,16 +5830,12 @@ pbm_load (struct frame *f, struct image *img) | |||
| 5702 | 5830 | ||
| 5703 | /* Maybe fill in the background field while we have ximg handy. */ | 5831 | /* Maybe fill in the background field while we have ximg handy. */ |
| 5704 | 5832 | ||
| 5705 | #ifdef USE_CAIRO | ||
| 5706 | set_cairo_image_surface (img, surface); | ||
| 5707 | #else | ||
| 5708 | if (NILP (image_spec_value (img->spec, QCbackground, NULL))) | 5833 | if (NILP (image_spec_value (img->spec, QCbackground, NULL))) |
| 5709 | /* Casting avoids a GCC warning. */ | 5834 | /* Casting avoids a GCC warning. */ |
| 5710 | IMAGE_BACKGROUND (img, f, (Emacs_Pix_Context)ximg); | 5835 | IMAGE_BACKGROUND (img, f, (Emacs_Pix_Context)ximg); |
| 5711 | 5836 | ||
| 5712 | /* Put ximg into the image. */ | 5837 | /* Put ximg into the image. */ |
| 5713 | image_put_x_image (f, img, ximg, 0); | 5838 | image_put_x_image (f, img, ximg, 0); |
| 5714 | #endif | ||
| 5715 | 5839 | ||
| 5716 | /* X and W32 versions did it here, MAC version above. ++kfs | 5840 | /* X and W32 versions did it here, MAC version above. ++kfs |
| 5717 | img->width = width; | 5841 | img->width = width; |
| @@ -6028,13 +6152,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) | |||
| 6028 | bool transparent_p; | 6152 | bool transparent_p; |
| 6029 | struct png_memory_storage tbr; /* Data to be read */ | 6153 | struct png_memory_storage tbr; /* Data to be read */ |
| 6030 | ptrdiff_t nbytes; | 6154 | ptrdiff_t nbytes; |
| 6031 | |||
| 6032 | #ifdef USE_CAIRO | ||
| 6033 | cairo_surface_t *surface; | ||
| 6034 | uint32_t *dataptr; | ||
| 6035 | #else | ||
| 6036 | Emacs_Pix_Container ximg, mask_img = NULL; | 6155 | Emacs_Pix_Container ximg, mask_img = NULL; |
| 6037 | #endif | ||
| 6038 | 6156 | ||
| 6039 | /* Find out what file to load. */ | 6157 | /* Find out what file to load. */ |
| 6040 | specified_file = image_spec_value (img->spec, QCfile, NULL); | 6158 | specified_file = image_spec_value (img->spec, QCfile, NULL); |
| @@ -6152,12 +6270,10 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) | |||
| 6152 | goto error; | 6270 | goto error; |
| 6153 | } | 6271 | } |
| 6154 | 6272 | ||
| 6155 | #ifndef USE_CAIRO | ||
| 6156 | /* Create the X image and pixmap now, so that the work below can be | 6273 | /* Create the X image and pixmap now, so that the work below can be |
| 6157 | omitted if the image is too large for X. */ | 6274 | omitted if the image is too large for X. */ |
| 6158 | if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) | 6275 | if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) |
| 6159 | goto error; | 6276 | goto error; |
| 6160 | #endif | ||
| 6161 | 6277 | ||
| 6162 | /* If image contains simply transparency data, we prefer to | 6278 | /* If image contains simply transparency data, we prefer to |
| 6163 | construct a clipping mask. */ | 6279 | construct a clipping mask. */ |
| @@ -6249,10 +6365,6 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) | |||
| 6249 | c->fp = NULL; | 6365 | c->fp = NULL; |
| 6250 | } | 6366 | } |
| 6251 | 6367 | ||
| 6252 | #ifdef USE_CAIRO | ||
| 6253 | surface = create_cairo_image_surface (width, height); | ||
| 6254 | dataptr = (uint32_t *) cairo_image_surface_get_data (surface); | ||
| 6255 | #else | ||
| 6256 | /* Create an image and pixmap serving as mask if the PNG image | 6368 | /* Create an image and pixmap serving as mask if the PNG image |
| 6257 | contains an alpha channel. */ | 6369 | contains an alpha channel. */ |
| 6258 | if (channels == 4 | 6370 | if (channels == 4 |
| @@ -6264,7 +6376,6 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) | |||
| 6264 | image_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP); | 6376 | image_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP); |
| 6265 | goto error; | 6377 | goto error; |
| 6266 | } | 6378 | } |
| 6267 | #endif | ||
| 6268 | 6379 | ||
| 6269 | /* Fill the X image and mask from PNG data. */ | 6380 | /* Fill the X image and mask from PNG data. */ |
| 6270 | init_color_table (); | 6381 | init_color_table (); |
| @@ -6277,18 +6388,10 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) | |||
| 6277 | { | 6388 | { |
| 6278 | int r, g, b; | 6389 | int r, g, b; |
| 6279 | 6390 | ||
| 6280 | #ifdef USE_CAIRO | ||
| 6281 | int a = 0xff; | ||
| 6282 | r = *p++; | ||
| 6283 | g = *p++; | ||
| 6284 | b = *p++; | ||
| 6285 | if (channels == 4) a = *p++; | ||
| 6286 | *dataptr++ = (a << 24) | (r << 16) | (g << 8) | b; | ||
| 6287 | #else | ||
| 6288 | r = *p++ << 8; | 6391 | r = *p++ << 8; |
| 6289 | g = *p++ << 8; | 6392 | g = *p++ << 8; |
| 6290 | b = *p++ << 8; | 6393 | b = *p++ << 8; |
| 6291 | XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b)); | 6394 | PUT_PIXEL (ximg, x, y, lookup_rgb_color (f, r, g, b)); |
| 6292 | /* An alpha channel, aka mask channel, associates variable | 6395 | /* An alpha channel, aka mask channel, associates variable |
| 6293 | transparency with an image. Where other image formats | 6396 | transparency with an image. Where other image formats |
| 6294 | support binary transparency---fully transparent or fully | 6397 | support binary transparency---fully transparent or fully |
| @@ -6308,10 +6411,9 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) | |||
| 6308 | if (channels == 4) | 6411 | if (channels == 4) |
| 6309 | { | 6412 | { |
| 6310 | if (mask_img) | 6413 | if (mask_img) |
| 6311 | XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN); | 6414 | PUT_PIXEL (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN); |
| 6312 | ++p; | 6415 | ++p; |
| 6313 | } | 6416 | } |
| 6314 | #endif | ||
| 6315 | } | 6417 | } |
| 6316 | } | 6418 | } |
| 6317 | 6419 | ||
| @@ -6322,7 +6424,14 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) | |||
| 6322 | png_color_16 *bg; | 6424 | png_color_16 *bg; |
| 6323 | if (png_get_bKGD (png_ptr, info_ptr, &bg)) | 6425 | if (png_get_bKGD (png_ptr, info_ptr, &bg)) |
| 6324 | { | 6426 | { |
| 6427 | #ifndef USE_CAIRO | ||
| 6325 | img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue); | 6428 | img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue); |
| 6429 | #else /* USE_CAIRO */ | ||
| 6430 | char color_name[30]; | ||
| 6431 | sprintf (color_name, "#%04x%04x%04x", bg->red, bg->green, bg->blue); | ||
| 6432 | img->background | ||
| 6433 | = image_alloc_image_color (f, img, build_string (color_name), 0); | ||
| 6434 | #endif /* USE_CAIRO */ | ||
| 6326 | img->background_valid = 1; | 6435 | img->background_valid = 1; |
| 6327 | } | 6436 | } |
| 6328 | } | 6437 | } |
| @@ -6341,9 +6450,6 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) | |||
| 6341 | img->width = width; | 6450 | img->width = width; |
| 6342 | img->height = height; | 6451 | img->height = height; |
| 6343 | 6452 | ||
| 6344 | #ifdef USE_CAIRO | ||
| 6345 | set_cairo_image_surface (img, surface); | ||
| 6346 | #else | ||
| 6347 | /* Maybe fill in the background field while we have ximg handy. | 6453 | /* Maybe fill in the background field while we have ximg handy. |
| 6348 | Casting avoids a GCC warning. */ | 6454 | Casting avoids a GCC warning. */ |
| 6349 | IMAGE_BACKGROUND (img, f, (Emacs_Pix_Context)ximg); | 6455 | IMAGE_BACKGROUND (img, f, (Emacs_Pix_Context)ximg); |
| @@ -6360,7 +6466,6 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) | |||
| 6360 | 6466 | ||
| 6361 | image_put_x_image (f, img, mask_img, 1); | 6467 | image_put_x_image (f, img, mask_img, 1); |
| 6362 | } | 6468 | } |
| 6363 | #endif | ||
| 6364 | 6469 | ||
| 6365 | return 1; | 6470 | return 1; |
| 6366 | } | 6471 | } |
| @@ -6774,10 +6879,8 @@ jpeg_load_body (struct frame *f, struct image *img, | |||
| 6774 | int row_stride, x, y; | 6879 | int row_stride, x, y; |
| 6775 | int width, height; | 6880 | int width, height; |
| 6776 | int i, ir, ig, ib; | 6881 | int i, ir, ig, ib; |
| 6777 | #ifndef USE_CAIRO | ||
| 6778 | unsigned long *colors; | 6882 | unsigned long *colors; |
| 6779 | Emacs_Pix_Container ximg = NULL; | 6883 | Emacs_Pix_Container ximg = NULL; |
| 6780 | #endif | ||
| 6781 | 6884 | ||
| 6782 | /* Open the JPEG file. */ | 6885 | /* Open the JPEG file. */ |
| 6783 | specified_file = image_spec_value (img->spec, QCfile, NULL); | 6886 | specified_file = image_spec_value (img->spec, QCfile, NULL); |
| @@ -6837,9 +6940,7 @@ jpeg_load_body (struct frame *f, struct image *img, | |||
| 6837 | jpeg_destroy_decompress (&mgr->cinfo); | 6940 | jpeg_destroy_decompress (&mgr->cinfo); |
| 6838 | 6941 | ||
| 6839 | /* If we already have an XImage, free that. */ | 6942 | /* If we already have an XImage, free that. */ |
| 6840 | #ifndef USE_CAIRO | ||
| 6841 | image_destroy_x_image (ximg); | 6943 | image_destroy_x_image (ximg); |
| 6842 | #endif | ||
| 6843 | /* Free pixmap and colors. */ | 6944 | /* Free pixmap and colors. */ |
| 6844 | image_clear_image (f, img); | 6945 | image_clear_image (f, img); |
| 6845 | return 0; | 6946 | return 0; |
| @@ -6870,23 +6971,19 @@ jpeg_load_body (struct frame *f, struct image *img, | |||
| 6870 | sys_longjmp (mgr->setjmp_buffer, 1); | 6971 | sys_longjmp (mgr->setjmp_buffer, 1); |
| 6871 | } | 6972 | } |
| 6872 | 6973 | ||
| 6873 | #ifndef USE_CAIRO | ||
| 6874 | /* Create X image and pixmap. */ | 6974 | /* Create X image and pixmap. */ |
| 6875 | if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) | 6975 | if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) |
| 6876 | { | 6976 | { |
| 6877 | mgr->failure_code = MY_JPEG_CANNOT_CREATE_X; | 6977 | mgr->failure_code = MY_JPEG_CANNOT_CREATE_X; |
| 6878 | sys_longjmp (mgr->setjmp_buffer, 1); | 6978 | sys_longjmp (mgr->setjmp_buffer, 1); |
| 6879 | } | 6979 | } |
| 6880 | #endif | ||
| 6881 | 6980 | ||
| 6882 | /* Allocate colors. When color quantization is used, | 6981 | /* Allocate colors. When color quantization is used, |
| 6883 | mgr->cinfo.actual_number_of_colors has been set with the number of | 6982 | mgr->cinfo.actual_number_of_colors has been set with the number of |
| 6884 | colors generated, and mgr->cinfo.colormap is a two-dimensional array | 6983 | colors generated, and mgr->cinfo.colormap is a two-dimensional array |
| 6885 | of color indices in the range 0..mgr->cinfo.actual_number_of_colors. | 6984 | of color indices in the range 0..mgr->cinfo.actual_number_of_colors. |
| 6886 | No more than 255 colors will be generated. */ | 6985 | No more than 255 colors will be generated. */ |
| 6887 | #ifndef USE_CAIRO | ||
| 6888 | USE_SAFE_ALLOCA; | 6986 | USE_SAFE_ALLOCA; |
| 6889 | #endif | ||
| 6890 | { | 6987 | { |
| 6891 | if (mgr->cinfo.out_color_components > 2) | 6988 | if (mgr->cinfo.out_color_components > 2) |
| 6892 | ir = 0, ig = 1, ib = 2; | 6989 | ir = 0, ig = 1, ib = 2; |
| @@ -6895,7 +6992,6 @@ jpeg_load_body (struct frame *f, struct image *img, | |||
| 6895 | else | 6992 | else |
| 6896 | ir = 0, ig = 0, ib = 0; | 6993 | ir = 0, ig = 0, ib = 0; |
| 6897 | 6994 | ||
| 6898 | #ifndef USE_CAIRO | ||
| 6899 | /* Use the color table mechanism because it handles colors that | 6995 | /* Use the color table mechanism because it handles colors that |
| 6900 | cannot be allocated nicely. Such colors will be replaced with | 6996 | cannot be allocated nicely. Such colors will be replaced with |
| 6901 | a default color, and we don't have to care about which colors | 6997 | a default color, and we don't have to care about which colors |
| @@ -6912,7 +7008,6 @@ jpeg_load_body (struct frame *f, struct image *img, | |||
| 6912 | int b = mgr->cinfo.colormap[ib][i] << 8; | 7008 | int b = mgr->cinfo.colormap[ib][i] << 8; |
| 6913 | colors[i] = lookup_rgb_color (f, r, g, b); | 7009 | colors[i] = lookup_rgb_color (f, r, g, b); |
| 6914 | } | 7010 | } |
| 6915 | #endif | ||
| 6916 | 7011 | ||
| 6917 | #ifdef COLOR_TABLE_SUPPORT | 7012 | #ifdef COLOR_TABLE_SUPPORT |
| 6918 | /* Remember those colors actually allocated. */ | 7013 | /* Remember those colors actually allocated. */ |
| @@ -6925,36 +7020,12 @@ jpeg_load_body (struct frame *f, struct image *img, | |||
| 6925 | row_stride = width * mgr->cinfo.output_components; | 7020 | row_stride = width * mgr->cinfo.output_components; |
| 6926 | buffer = mgr->cinfo.mem->alloc_sarray ((j_common_ptr) &mgr->cinfo, | 7021 | buffer = mgr->cinfo.mem->alloc_sarray ((j_common_ptr) &mgr->cinfo, |
| 6927 | JPOOL_IMAGE, row_stride, 1); | 7022 | JPOOL_IMAGE, row_stride, 1); |
| 6928 | #ifdef USE_CAIRO | ||
| 6929 | { | ||
| 6930 | cairo_surface_t *surface = create_cairo_image_surface (width, height); | ||
| 6931 | uint32_t *dataptr = (uint32_t *) cairo_image_surface_get_data (surface); | ||
| 6932 | int r, g, b; | ||
| 6933 | |||
| 6934 | for (y = 0; y < height; ++y) | ||
| 6935 | { | ||
| 6936 | jpeg_read_scanlines (&mgr->cinfo, buffer, 1); | ||
| 6937 | |||
| 6938 | for (x = 0; x < width; ++x) | ||
| 6939 | { | ||
| 6940 | i = buffer[0][x]; | ||
| 6941 | r = mgr->cinfo.colormap[ir][i]; | ||
| 6942 | g = mgr->cinfo.colormap[ig][i]; | ||
| 6943 | b = mgr->cinfo.colormap[ib][i]; | ||
| 6944 | *dataptr++ = (0xffu << 24) | (r << 16) | (g << 8) | b; | ||
| 6945 | } | ||
| 6946 | } | ||
| 6947 | |||
| 6948 | set_cairo_image_surface (img, surface); | ||
| 6949 | } | ||
| 6950 | #else | ||
| 6951 | for (y = 0; y < height; ++y) | 7023 | for (y = 0; y < height; ++y) |
| 6952 | { | 7024 | { |
| 6953 | jpeg_read_scanlines (&mgr->cinfo, buffer, 1); | 7025 | jpeg_read_scanlines (&mgr->cinfo, buffer, 1); |
| 6954 | for (x = 0; x < mgr->cinfo.output_width; ++x) | 7026 | for (x = 0; x < mgr->cinfo.output_width; ++x) |
| 6955 | XPutPixel (ximg, x, y, colors[buffer[0][x]]); | 7027 | PUT_PIXEL (ximg, x, y, colors[buffer[0][x]]); |
| 6956 | } | 7028 | } |
| 6957 | #endif | ||
| 6958 | 7029 | ||
| 6959 | /* Clean up. */ | 7030 | /* Clean up. */ |
| 6960 | jpeg_finish_decompress (&mgr->cinfo); | 7031 | jpeg_finish_decompress (&mgr->cinfo); |
| @@ -6962,7 +7033,6 @@ jpeg_load_body (struct frame *f, struct image *img, | |||
| 6962 | if (fp) | 7033 | if (fp) |
| 6963 | fclose (fp); | 7034 | fclose (fp); |
| 6964 | 7035 | ||
| 6965 | #ifndef USE_CAIRO | ||
| 6966 | /* Maybe fill in the background field while we have ximg handy. */ | 7036 | /* Maybe fill in the background field while we have ximg handy. */ |
| 6967 | if (NILP (image_spec_value (img->spec, QCbackground, NULL))) | 7037 | if (NILP (image_spec_value (img->spec, QCbackground, NULL))) |
| 6968 | /* Casting avoids a GCC warning. */ | 7038 | /* Casting avoids a GCC warning. */ |
| @@ -6971,7 +7041,6 @@ jpeg_load_body (struct frame *f, struct image *img, | |||
| 6971 | /* Put ximg into the image. */ | 7041 | /* Put ximg into the image. */ |
| 6972 | image_put_x_image (f, img, ximg, 0); | 7042 | image_put_x_image (f, img, ximg, 0); |
| 6973 | SAFE_FREE (); | 7043 | SAFE_FREE (); |
| 6974 | #endif | ||
| 6975 | return 1; | 7044 | return 1; |
| 6976 | } | 7045 | } |
| 6977 | 7046 | ||
| @@ -7384,28 +7453,6 @@ tiff_load (struct frame *f, struct image *img) | |||
| 7384 | return 0; | 7453 | return 0; |
| 7385 | } | 7454 | } |
| 7386 | 7455 | ||
| 7387 | #ifdef USE_CAIRO | ||
| 7388 | { | ||
| 7389 | cairo_surface_t *surface = create_cairo_image_surface (width, height); | ||
| 7390 | uint32_t *dataptr = (uint32_t *) cairo_image_surface_get_data (surface); | ||
| 7391 | |||
| 7392 | for (y = 0; y < height; ++y) | ||
| 7393 | { | ||
| 7394 | uint32 *row = buf + (height - 1 - y) * width; | ||
| 7395 | for (x = 0; x < width; ++x) | ||
| 7396 | { | ||
| 7397 | uint32 abgr = row[x]; | ||
| 7398 | int r = TIFFGetR (abgr); | ||
| 7399 | int g = TIFFGetG (abgr); | ||
| 7400 | int b = TIFFGetB (abgr); | ||
| 7401 | int a = TIFFGetA (abgr); | ||
| 7402 | *dataptr++ = (a << 24) | (r << 16) | (g << 8) | b; | ||
| 7403 | } | ||
| 7404 | } | ||
| 7405 | |||
| 7406 | set_cairo_image_surface (img, surface); | ||
| 7407 | } | ||
| 7408 | #else | ||
| 7409 | /* Initialize the color table. */ | 7456 | /* Initialize the color table. */ |
| 7410 | init_color_table (); | 7457 | init_color_table (); |
| 7411 | 7458 | ||
| @@ -7420,7 +7467,7 @@ tiff_load (struct frame *f, struct image *img) | |||
| 7420 | int r = TIFFGetR (abgr) << 8; | 7467 | int r = TIFFGetR (abgr) << 8; |
| 7421 | int g = TIFFGetG (abgr) << 8; | 7468 | int g = TIFFGetG (abgr) << 8; |
| 7422 | int b = TIFFGetB (abgr) << 8; | 7469 | int b = TIFFGetB (abgr) << 8; |
| 7423 | XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b)); | 7470 | PUT_PIXEL (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b)); |
| 7424 | } | 7471 | } |
| 7425 | } | 7472 | } |
| 7426 | 7473 | ||
| @@ -7441,8 +7488,6 @@ tiff_load (struct frame *f, struct image *img) | |||
| 7441 | /* Put ximg into the image. */ | 7488 | /* Put ximg into the image. */ |
| 7442 | image_put_x_image (f, img, ximg, 0); | 7489 | image_put_x_image (f, img, ximg, 0); |
| 7443 | 7490 | ||
| 7444 | #endif /* ! USE_CAIRO */ | ||
| 7445 | |||
| 7446 | xfree (buf); | 7491 | xfree (buf); |
| 7447 | return 1; | 7492 | return 1; |
| 7448 | } | 7493 | } |
| @@ -7819,26 +7864,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 7819 | } | 7864 | } |
| 7820 | } | 7865 | } |
| 7821 | 7866 | ||
| 7822 | #ifdef USE_CAIRO | ||
| 7823 | cairo_surface_t *surface = create_cairo_image_surface (width, height); | ||
| 7824 | uint32_t *data32 = (uint32_t *) cairo_image_surface_get_data (surface); | ||
| 7825 | if (STRINGP (specified_bg)) | ||
| 7826 | { | ||
| 7827 | Emacs_Color color; | ||
| 7828 | if (FRAME_TERMINAL (f)->defined_color_hook | ||
| 7829 | (f, SSDATA (specified_bg), &color, false, false)) | ||
| 7830 | { | ||
| 7831 | uint32_t *dataptr = data32; | ||
| 7832 | int r = color.red/256; | ||
| 7833 | int g = color.green/256; | ||
| 7834 | int b = color.blue/256; | ||
| 7835 | |||
| 7836 | for (y = 0; y < height; ++y) | ||
| 7837 | for (x = 0; x < width; ++x) | ||
| 7838 | *dataptr++ = (0xffu << 24) | (r << 16) | (g << 8) | b; | ||
| 7839 | } | ||
| 7840 | } | ||
| 7841 | #else | ||
| 7842 | /* Create the X image and pixmap. */ | 7867 | /* Create the X image and pixmap. */ |
| 7843 | Emacs_Pix_Container ximg; | 7868 | Emacs_Pix_Container ximg; |
| 7844 | if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) | 7869 | if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) |
| @@ -7851,22 +7876,31 @@ gif_load (struct frame *f, struct image *img) | |||
| 7851 | Full animated GIF support requires more here (see the gif89 spec, | 7876 | Full animated GIF support requires more here (see the gif89 spec, |
| 7852 | disposal methods). Let's simply assume that the part not covered | 7877 | disposal methods). Let's simply assume that the part not covered |
| 7853 | by a sub-image is in the frame's background color. */ | 7878 | by a sub-image is in the frame's background color. */ |
| 7879 | unsigned long frame_bg; | ||
| 7880 | #ifndef USE_CAIRO | ||
| 7881 | frame_bg = FRAME_BACKGROUND_PIXEL (f); | ||
| 7882 | #else /* USE_CAIRO */ | ||
| 7883 | { | ||
| 7884 | Emacs_Color color; | ||
| 7885 | FRAME_TERMINAL (f)->query_frame_background_color (f, &color); | ||
| 7886 | frame_bg = lookup_rgb_color (f, color.red, color.green, color.blue); | ||
| 7887 | } | ||
| 7888 | #endif /* USE_CAIRO */ | ||
| 7854 | for (y = 0; y < img->corners[TOP_CORNER]; ++y) | 7889 | for (y = 0; y < img->corners[TOP_CORNER]; ++y) |
| 7855 | for (x = 0; x < width; ++x) | 7890 | for (x = 0; x < width; ++x) |
| 7856 | XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); | 7891 | PUT_PIXEL (ximg, x, y, frame_bg); |
| 7857 | 7892 | ||
| 7858 | for (y = img->corners[BOT_CORNER]; y < height; ++y) | 7893 | for (y = img->corners[BOT_CORNER]; y < height; ++y) |
| 7859 | for (x = 0; x < width; ++x) | 7894 | for (x = 0; x < width; ++x) |
| 7860 | XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); | 7895 | PUT_PIXEL (ximg, x, y, frame_bg); |
| 7861 | 7896 | ||
| 7862 | for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y) | 7897 | for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y) |
| 7863 | { | 7898 | { |
| 7864 | for (x = 0; x < img->corners[LEFT_CORNER]; ++x) | 7899 | for (x = 0; x < img->corners[LEFT_CORNER]; ++x) |
| 7865 | XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); | 7900 | PUT_PIXEL (ximg, x, y, frame_bg); |
| 7866 | for (x = img->corners[RIGHT_CORNER]; x < width; ++x) | 7901 | for (x = img->corners[RIGHT_CORNER]; x < width; ++x) |
| 7867 | XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); | 7902 | PUT_PIXEL (ximg, x, y, frame_bg); |
| 7868 | } | 7903 | } |
| 7869 | #endif | ||
| 7870 | 7904 | ||
| 7871 | /* Read the GIF image into the X image. */ | 7905 | /* Read the GIF image into the X image. */ |
| 7872 | 7906 | ||
| @@ -7877,12 +7911,17 @@ gif_load (struct frame *f, struct image *img) | |||
| 7877 | 7911 | ||
| 7878 | init_color_table (); | 7912 | init_color_table (); |
| 7879 | 7913 | ||
| 7880 | #ifndef USE_CAIRO | ||
| 7881 | unsigned long bgcolor UNINIT; | 7914 | unsigned long bgcolor UNINIT; |
| 7882 | if (STRINGP (specified_bg)) | 7915 | if (STRINGP (specified_bg)) |
| 7883 | bgcolor = image_alloc_image_color (f, img, specified_bg, | 7916 | { |
| 7884 | FRAME_BACKGROUND_PIXEL (f)); | 7917 | bgcolor = image_alloc_image_color (f, img, specified_bg, |
| 7918 | FRAME_BACKGROUND_PIXEL (f)); | ||
| 7919 | #ifdef USE_CAIRO | ||
| 7920 | Emacs_Color color = {.pixel = bgcolor}; | ||
| 7921 | FRAME_TERMINAL (f)->query_colors (f, &color, 1); | ||
| 7922 | bgcolor = lookup_rgb_color (f, color.red, color.green, color.blue); | ||
| 7885 | #endif | 7923 | #endif |
| 7924 | } | ||
| 7886 | 7925 | ||
| 7887 | for (j = 0; j <= idx; ++j) | 7926 | for (j = 0; j <= idx; ++j) |
| 7888 | { | 7927 | { |
| @@ -7930,7 +7969,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 7930 | if (!gif_color_map) | 7969 | if (!gif_color_map) |
| 7931 | gif_color_map = gif->SColorMap; | 7970 | gif_color_map = gif->SColorMap; |
| 7932 | 7971 | ||
| 7933 | #ifndef USE_CAIRO | ||
| 7934 | /* Allocate subimage colors. */ | 7972 | /* Allocate subimage colors. */ |
| 7935 | unsigned long pixel_colors[256] = { 0, }; | 7973 | unsigned long pixel_colors[256] = { 0, }; |
| 7936 | 7974 | ||
| @@ -7939,7 +7977,7 @@ gif_load (struct frame *f, struct image *img) | |||
| 7939 | { | 7977 | { |
| 7940 | if (transparency_color_index == i) | 7978 | if (transparency_color_index == i) |
| 7941 | pixel_colors[i] = STRINGP (specified_bg) | 7979 | pixel_colors[i] = STRINGP (specified_bg) |
| 7942 | ? bgcolor : FRAME_BACKGROUND_PIXEL (f); | 7980 | ? bgcolor : frame_bg; |
| 7943 | else | 7981 | else |
| 7944 | { | 7982 | { |
| 7945 | int r = gif_color_map->Colors[i].Red << 8; | 7983 | int r = gif_color_map->Colors[i].Red << 8; |
| @@ -7948,7 +7986,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 7948 | pixel_colors[i] = lookup_rgb_color (f, r, g, b); | 7986 | pixel_colors[i] = lookup_rgb_color (f, r, g, b); |
| 7949 | } | 7987 | } |
| 7950 | } | 7988 | } |
| 7951 | #endif | ||
| 7952 | 7989 | ||
| 7953 | /* Apply the pixel values. */ | 7990 | /* Apply the pixel values. */ |
| 7954 | if (GIFLIB_MAJOR < 5 && gif->SavedImages[j].ImageDesc.Interlace) | 7991 | if (GIFLIB_MAJOR < 5 && gif->SavedImages[j].ImageDesc.Interlace) |
| @@ -7967,21 +8004,9 @@ gif_load (struct frame *f, struct image *img) | |||
| 7967 | int c = raster[y * subimg_width + x]; | 8004 | int c = raster[y * subimg_width + x]; |
| 7968 | if (transparency_color_index != c || disposal != 1) | 8005 | if (transparency_color_index != c || disposal != 1) |
| 7969 | { | 8006 | { |
| 7970 | #ifdef USE_CAIRO | 8007 | PUT_PIXEL (ximg, x + subimg_left, row + subimg_top, |
| 7971 | uint32_t *dataptr = | ||
| 7972 | (data32 + ((row + subimg_top) * width | ||
| 7973 | + x + subimg_left)); | ||
| 7974 | int r = gif_color_map->Colors[c].Red; | ||
| 7975 | int g = gif_color_map->Colors[c].Green; | ||
| 7976 | int b = gif_color_map->Colors[c].Blue; | ||
| 7977 | |||
| 7978 | if (transparency_color_index != c) | ||
| 7979 | *dataptr = (0xffu << 24) | (r << 16) | (g << 8) | b; | ||
| 7980 | #else | ||
| 7981 | XPutPixel (ximg, x + subimg_left, row + subimg_top, | ||
| 7982 | pixel_colors[c]); | 8008 | pixel_colors[c]); |
| 7983 | #endif | 8009 | } |
| 7984 | } | ||
| 7985 | } | 8010 | } |
| 7986 | } | 8011 | } |
| 7987 | } | 8012 | } |
| @@ -7993,19 +8018,8 @@ gif_load (struct frame *f, struct image *img) | |||
| 7993 | int c = raster[y * subimg_width + x]; | 8018 | int c = raster[y * subimg_width + x]; |
| 7994 | if (transparency_color_index != c || disposal != 1) | 8019 | if (transparency_color_index != c || disposal != 1) |
| 7995 | { | 8020 | { |
| 7996 | #ifdef USE_CAIRO | 8021 | PUT_PIXEL (ximg, x + subimg_left, y + subimg_top, |
| 7997 | uint32_t *dataptr = | ||
| 7998 | (data32 + ((y + subimg_top) * width | ||
| 7999 | + x + subimg_left)); | ||
| 8000 | int r = gif_color_map->Colors[c].Red; | ||
| 8001 | int g = gif_color_map->Colors[c].Green; | ||
| 8002 | int b = gif_color_map->Colors[c].Blue; | ||
| 8003 | if (transparency_color_index != c) | ||
| 8004 | *dataptr = (0xffu << 24) | (r << 16) | (g << 8) | b; | ||
| 8005 | #else | ||
| 8006 | XPutPixel (ximg, x + subimg_left, y + subimg_top, | ||
| 8007 | pixel_colors[c]); | 8022 | pixel_colors[c]); |
| 8008 | #endif | ||
| 8009 | } | 8023 | } |
| 8010 | } | 8024 | } |
| 8011 | } | 8025 | } |
| @@ -8064,9 +8078,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 8064 | #endif | 8078 | #endif |
| 8065 | } | 8079 | } |
| 8066 | 8080 | ||
| 8067 | #ifdef USE_CAIRO | ||
| 8068 | set_cairo_image_surface (img, surface); | ||
| 8069 | #else | ||
| 8070 | /* Maybe fill in the background field while we have ximg handy. */ | 8081 | /* Maybe fill in the background field while we have ximg handy. */ |
| 8071 | if (NILP (image_spec_value (img->spec, QCbackground, NULL))) | 8082 | if (NILP (image_spec_value (img->spec, QCbackground, NULL))) |
| 8072 | /* Casting avoids a GCC warning. */ | 8083 | /* Casting avoids a GCC warning. */ |
| @@ -8074,7 +8085,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 8074 | 8085 | ||
| 8075 | /* Put ximg into the image. */ | 8086 | /* Put ximg into the image. */ |
| 8076 | image_put_x_image (f, img, ximg, 0); | 8087 | image_put_x_image (f, img, ximg, 0); |
| 8077 | #endif | ||
| 8078 | 8088 | ||
| 8079 | return 1; | 8089 | return 1; |
| 8080 | } | 8090 | } |
| @@ -8453,9 +8463,7 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 8453 | int width, height; | 8463 | int width, height; |
| 8454 | size_t image_width, image_height; | 8464 | size_t image_width, image_height; |
| 8455 | MagickBooleanType status; | 8465 | MagickBooleanType status; |
| 8456 | #ifndef USE_CAIRO | ||
| 8457 | Emacs_Pix_Container ximg; | 8466 | Emacs_Pix_Container ximg; |
| 8458 | #endif | ||
| 8459 | int x, y; | 8467 | int x, y; |
| 8460 | MagickWand *image_wand; | 8468 | MagickWand *image_wand; |
| 8461 | PixelIterator *iterator; | 8469 | PixelIterator *iterator; |
| @@ -8469,9 +8477,6 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 8469 | double rotation; | 8477 | double rotation; |
| 8470 | char hint_buffer[MaxTextExtent]; | 8478 | char hint_buffer[MaxTextExtent]; |
| 8471 | char *filename_hint = NULL; | 8479 | char *filename_hint = NULL; |
| 8472 | #ifdef USE_CAIRO | ||
| 8473 | cairo_surface_t *surface; | ||
| 8474 | #endif | ||
| 8475 | 8480 | ||
| 8476 | /* Initialize the ImageMagick environment. */ | 8481 | /* Initialize the ImageMagick environment. */ |
| 8477 | static bool imagemagick_initialized; | 8482 | static bool imagemagick_initialized; |
| @@ -8685,11 +8690,6 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 8685 | method is also well tested. Some aspects of this method are | 8690 | method is also well tested. Some aspects of this method are |
| 8686 | ad-hoc and needs to be more researched. */ | 8691 | ad-hoc and needs to be more researched. */ |
| 8687 | void *dataptr; | 8692 | void *dataptr; |
| 8688 | #ifdef USE_CAIRO | ||
| 8689 | surface = create_cairo_image_surface (width, height); | ||
| 8690 | const char *exportdepth = "BGRA"; | ||
| 8691 | dataptr = cairo_image_surface_get_data (surface); | ||
| 8692 | #else | ||
| 8693 | int imagedepth = 24; /*MagickGetImageDepth(image_wand);*/ | 8693 | int imagedepth = 24; /*MagickGetImageDepth(image_wand);*/ |
| 8694 | const char *exportdepth = imagedepth <= 8 ? "I" : "BGRP"; /*"RGBP";*/ | 8694 | const char *exportdepth = imagedepth <= 8 ? "I" : "BGRP"; /*"RGBP";*/ |
| 8695 | /* Try to create a x pixmap to hold the imagemagick pixmap. */ | 8695 | /* Try to create a x pixmap to hold the imagemagick pixmap. */ |
| @@ -8703,7 +8703,6 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 8703 | goto imagemagick_error; | 8703 | goto imagemagick_error; |
| 8704 | } | 8704 | } |
| 8705 | dataptr = ximg->data; | 8705 | dataptr = ximg->data; |
| 8706 | #endif /* not USE_CAIRO */ | ||
| 8707 | 8706 | ||
| 8708 | /* Oddly, the below code doesn't seem to work:*/ | 8707 | /* Oddly, the below code doesn't seem to work:*/ |
| 8709 | /* switch(ximg->bitmap_unit){ */ | 8708 | /* switch(ximg->bitmap_unit){ */ |
| @@ -8734,11 +8733,6 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 8734 | size_t image_height; | 8733 | size_t image_height; |
| 8735 | double quantum_range = QuantumRange; | 8734 | double quantum_range = QuantumRange; |
| 8736 | MagickRealType color_scale = 65535.0 / quantum_range; | 8735 | MagickRealType color_scale = 65535.0 / quantum_range; |
| 8737 | #ifdef USE_CAIRO | ||
| 8738 | surface = create_cairo_image_surface (width, height); | ||
| 8739 | uint32_t *dataptr = (uint32_t *) cairo_image_surface_get_data (surface); | ||
| 8740 | color_scale /= 256; | ||
| 8741 | #else | ||
| 8742 | /* Try to create a x pixmap to hold the imagemagick pixmap. */ | 8736 | /* Try to create a x pixmap to hold the imagemagick pixmap. */ |
| 8743 | if (!image_create_x_image_and_pixmap (f, img, width, height, 0, | 8737 | if (!image_create_x_image_and_pixmap (f, img, width, height, 0, |
| 8744 | &ximg, 0)) | 8738 | &ximg, 0)) |
| @@ -8749,7 +8743,6 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 8749 | image_error ("Imagemagick X bitmap allocation failure"); | 8743 | image_error ("Imagemagick X bitmap allocation failure"); |
| 8750 | goto imagemagick_error; | 8744 | goto imagemagick_error; |
| 8751 | } | 8745 | } |
| 8752 | #endif | ||
| 8753 | 8746 | ||
| 8754 | /* Copy imagemagick image to x with primitive yet robust pixel | 8747 | /* Copy imagemagick image to x with primitive yet robust pixel |
| 8755 | pusher loop. This has been tested a lot with many different | 8748 | pusher loop. This has been tested a lot with many different |
| @@ -8762,9 +8755,7 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 8762 | #ifdef COLOR_TABLE_SUPPORT | 8755 | #ifdef COLOR_TABLE_SUPPORT |
| 8763 | free_color_table (); | 8756 | free_color_table (); |
| 8764 | #endif | 8757 | #endif |
| 8765 | #ifndef USE_CAIRO | ||
| 8766 | image_destroy_x_image (ximg); | 8758 | image_destroy_x_image (ximg); |
| 8767 | #endif | ||
| 8768 | image_error ("Imagemagick pixel iterator creation failed"); | 8759 | image_error ("Imagemagick pixel iterator creation failed"); |
| 8769 | goto imagemagick_error; | 8760 | goto imagemagick_error; |
| 8770 | } | 8761 | } |
| @@ -8780,27 +8771,16 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 8780 | for (x = 0; x < xlim; x++) | 8771 | for (x = 0; x < xlim; x++) |
| 8781 | { | 8772 | { |
| 8782 | PixelGetMagickColor (pixels[x], &pixel); | 8773 | PixelGetMagickColor (pixels[x], &pixel); |
| 8783 | #ifdef USE_CAIRO | 8774 | PUT_PIXEL (ximg, x, y, |
| 8784 | dataptr[width * y + x] = | ||
| 8785 | lookup_rgb_color (f, | ||
| 8786 | color_scale * pixel.red, | ||
| 8787 | color_scale * pixel.green, | ||
| 8788 | color_scale * pixel.blue); | ||
| 8789 | #else | ||
| 8790 | XPutPixel (ximg, x, y, | ||
| 8791 | lookup_rgb_color (f, | 8775 | lookup_rgb_color (f, |
| 8792 | color_scale * pixel.red, | 8776 | color_scale * pixel.red, |
| 8793 | color_scale * pixel.green, | 8777 | color_scale * pixel.green, |
| 8794 | color_scale * pixel.blue)); | 8778 | color_scale * pixel.blue)); |
| 8795 | #endif | ||
| 8796 | } | 8779 | } |
| 8797 | } | 8780 | } |
| 8798 | DestroyPixelIterator (iterator); | 8781 | DestroyPixelIterator (iterator); |
| 8799 | } | 8782 | } |
| 8800 | 8783 | ||
| 8801 | #ifdef USE_CAIRO | ||
| 8802 | set_cairo_image_surface (img, surface); | ||
| 8803 | #else | ||
| 8804 | #ifdef COLOR_TABLE_SUPPORT | 8784 | #ifdef COLOR_TABLE_SUPPORT |
| 8805 | /* Remember colors allocated for this image. */ | 8785 | /* Remember colors allocated for this image. */ |
| 8806 | img->colors = colors_in_color_table (&img->ncolors); | 8786 | img->colors = colors_in_color_table (&img->ncolors); |
| @@ -8812,7 +8792,6 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 8812 | 8792 | ||
| 8813 | /* Put ximg into the image. */ | 8793 | /* Put ximg into the image. */ |
| 8814 | image_put_x_image (f, img, ximg, 0); | 8794 | image_put_x_image (f, img, ximg, 0); |
| 8815 | #endif | ||
| 8816 | 8795 | ||
| 8817 | /* Final cleanup. image_wand should be the only resource left. */ | 8796 | /* Final cleanup. image_wand should be the only resource left. */ |
| 8818 | DestroyMagickWand (image_wand); | 8797 | DestroyMagickWand (image_wand); |
| @@ -9257,33 +9236,6 @@ svg_load_image (struct frame *f, struct image *img, char *contents, | |||
| 9257 | eassert (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8); | 9236 | eassert (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8); |
| 9258 | 9237 | ||
| 9259 | { | 9238 | { |
| 9260 | #ifdef USE_CAIRO | ||
| 9261 | cairo_surface_t *surface = create_cairo_image_surface (width, height); | ||
| 9262 | uint32_t *dataptr = (uint32_t *) cairo_image_surface_get_data (surface); | ||
| 9263 | uint32_t bgcolor = get_spec_bg_or_alpha_as_argb (img, f); | ||
| 9264 | |||
| 9265 | for (int y = 0; y < height; ++y) | ||
| 9266 | { | ||
| 9267 | const guchar *iconptr = pixels + y * rowstride; | ||
| 9268 | |||
| 9269 | for (int x = 0; x < width; ++x) | ||
| 9270 | { | ||
| 9271 | if (iconptr[3] == 0) | ||
| 9272 | *dataptr = bgcolor; | ||
| 9273 | else | ||
| 9274 | *dataptr = (iconptr[0] << 16) | ||
| 9275 | | (iconptr[1] << 8) | ||
| 9276 | | iconptr[2] | ||
| 9277 | | (iconptr[3] << 24); | ||
| 9278 | |||
| 9279 | iconptr += 4; | ||
| 9280 | ++dataptr; | ||
| 9281 | } | ||
| 9282 | } | ||
| 9283 | |||
| 9284 | set_cairo_image_surface (img, surface); | ||
| 9285 | g_object_unref (pixbuf); | ||
| 9286 | #else | ||
| 9287 | /* Try to create a x pixmap to hold the svg pixmap. */ | 9239 | /* Try to create a x pixmap to hold the svg pixmap. */ |
| 9288 | Emacs_Pix_Container ximg; | 9240 | Emacs_Pix_Container ximg; |
| 9289 | if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) | 9241 | if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) |
| @@ -9333,7 +9285,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents, | |||
| 9333 | blue = ((blue * opacity) | 9285 | blue = ((blue * opacity) |
| 9334 | + (background.blue * ((1 << 8) - opacity))); | 9286 | + (background.blue * ((1 << 8) - opacity))); |
| 9335 | 9287 | ||
| 9336 | XPutPixel (ximg, x, y, lookup_rgb_color (f, red, green, blue)); | 9288 | PUT_PIXEL (ximg, x, y, lookup_rgb_color (f, red, green, blue)); |
| 9337 | } | 9289 | } |
| 9338 | 9290 | ||
| 9339 | pixels += rowstride - 4 * width; | 9291 | pixels += rowstride - 4 * width; |
| @@ -9356,7 +9308,6 @@ svg_load_image (struct frame *f, struct image *img, char *contents, | |||
| 9356 | 9308 | ||
| 9357 | /* Put ximg into the image. */ | 9309 | /* Put ximg into the image. */ |
| 9358 | image_put_x_image (f, img, ximg, 0); | 9310 | image_put_x_image (f, img, ximg, 0); |
| 9359 | #endif /* ! USE_CAIRO */ | ||
| 9360 | } | 9311 | } |
| 9361 | 9312 | ||
| 9362 | return 1; | 9313 | return 1; |
| @@ -9379,9 +9330,9 @@ svg_load_image (struct frame *f, struct image *img, char *contents, | |||
| 9379 | Ghostscript | 9330 | Ghostscript |
| 9380 | ***********************************************************************/ | 9331 | ***********************************************************************/ |
| 9381 | 9332 | ||
| 9382 | #ifdef HAVE_X_WINDOWS | 9333 | #if defined HAVE_X_WINDOWS && !defined USE_CAIRO |
| 9383 | #define HAVE_GHOSTSCRIPT 1 | 9334 | #define HAVE_GHOSTSCRIPT 1 |
| 9384 | #endif /* HAVE_X_WINDOWS */ | 9335 | #endif /* HAVE_X_WINDOWS && !USE_CAIRO */ |
| 9385 | 9336 | ||
| 9386 | #ifdef HAVE_GHOSTSCRIPT | 9337 | #ifdef HAVE_GHOSTSCRIPT |
| 9387 | 9338 | ||