aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu2013-06-28 11:37:23 +0900
committerYAMAMOTO Mitsuharu2013-06-28 11:37:23 +0900
commit547c92696e78d2b332b6e8a259df640ea25a8932 (patch)
tree86d2c5b61482c311b360ab1d9e5d7bffc626aed6 /src
parent9c8d35d532867c48ff8867466da20d70e931c5bc (diff)
downloademacs-547c92696e78d2b332b6e8a259df640ea25a8932.tar.gz
emacs-547c92696e78d2b332b6e8a259df640ea25a8932.zip
Defer image data transfer between X client and server until actual display happens.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog36
-rw-r--r--src/dispextern.h8
-rw-r--r--src/image.c459
3 files changed, 338 insertions, 165 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 837d946a26e..e48d3fd9f2b 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,39 @@
12013-06-28 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
2
3 Defer image data transfer between X client and server until actual
4 display happens.
5
6 * dispextern.h (struct image) [HAVE_X_WINDOWS]: New members `ximg'
7 and `mask_img'.
8
9 * image.c (Destroy_Image): Remove.
10 (x_clear_image_1): New arg `flags' instead of 3 bools `pixmap_p',
11 `mask_p', and `colors_p'. All uses changed.
12 (x_clear_image_1) [HAVE_X_WINDOWS]: Destroy `ximg' and `mask_img'.
13 (CLEAR_IMAGE_PIXMAP, CLEAR_IMAGE_MASK, CLEAR_IMAGE_COLORS): New
14 macros for `flags' arg to x_clear_image_1.
15 (postprocess_image, xpm_load_image, x_build_heuristic_mask)
16 (png_load_body): Use x_clear_image_1 instead of Free_Pixmap.
17 (NO_PIXMAP, XGetImage) [HAVE_NS]: Remove.
18 (image_get_x_image_or_dc, image_unget_x_image_or_dc)
19 (image_get_x_image, image_unget_x_image): New functions or macros.
20 (image_background, image_background_transparent, x_to_xcolors)
21 (x_build_heuristic_mask): Use image_get_x_image_or_dc instead of
22 XGetImage or CreateCompatibleDC. Use image_unget_x_image_or_dc
23 instead of Destroy_Image.
24 (image_create_x_image_and_pixmap, image_put_x_image): New functions.
25 (xpm_load_image, x_from_xcolors, x_build_heuristic_mask, pbm_load)
26 (png_load_body, jpeg_load_body, tiff_load, gif_load)
27 (imagemagick_load_image, svg_load_image): Use them instead of
28 x_create_x_image_and_pixmap, and x_put_x_image followed by
29 x_destroy_x_image, respectively.
30 (xpm_load) [HAVE_XPM && !HAVE_NTGUI]: Use XpmReadFileToImage and
31 XpmCreateImageFromBuffer instead of XpmReadFileToPixmap and
32 XpmCreatePixmapFromBuffer. Create pixmaps. Fill background and
33 background_transparent fields.
34 (image_sync_to_pixmaps) [HAVE_X_WINDOWS]: New function.
35 (prepare_image_for_display, x_disable_image) [HAVE_X_WINDOWS]: Use it.
36
12013-06-27 Paul Eggert <eggert@cs.ucla.edu> 372013-06-27 Paul Eggert <eggert@cs.ucla.edu>
2 38
3 Do not tickle glib SIGCHLD handling if Cygwin (Bug#14569). 39 Do not tickle glib SIGCHLD handling if Cygwin (Bug#14569).
diff --git a/src/dispextern.h b/src/dispextern.h
index 401b3f2f6ae..a1dbc5e2024 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2870,6 +2870,14 @@ struct image
2870 /* Pixmaps of the image. */ 2870 /* Pixmaps of the image. */
2871 Pixmap pixmap, mask; 2871 Pixmap pixmap, mask;
2872 2872
2873#ifdef HAVE_X_WINDOWS
2874 /* X images of the image, corresponding to the above Pixmaps.
2875 Non-NULL means it and its Pixmap counterpart may be out of sync
2876 and the latter is outdated. NULL means the X image has been
2877 synchronized to Pixmap. */
2878 XImagePtr ximg, mask_img;
2879#endif
2880
2873 /* Colors allocated for this image, if any. Allocated via xmalloc. */ 2881 /* Colors allocated for this image, if any. Allocated via xmalloc. */
2874 unsigned long *colors; 2882 unsigned long *colors;
2875 int ncolors; 2883 int ncolors;
diff --git a/src/image.c b/src/image.c
index b65ee7df789..52aa743e4c7 100644
--- a/src/image.c
+++ b/src/image.c
@@ -106,8 +106,6 @@ typedef struct ns_bitmap_record Bitmap_Record;
106#define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y) 106#define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y)
107#define NO_PIXMAP 0 107#define NO_PIXMAP 0
108 108
109#define ZPixmap 0
110
111#define PIX_MASK_RETAIN 0 109#define PIX_MASK_RETAIN 0
112#define PIX_MASK_DRAW 1 110#define PIX_MASK_DRAW 1
113 111
@@ -146,16 +144,6 @@ Lisp_Object QCmax_width, QCmax_height;
146 data more than once will not be caught. */ 144 data more than once will not be caught. */
147 145
148#ifdef HAVE_NS 146#ifdef HAVE_NS
149XImagePtr
150XGetImage (Display *display, Pixmap pixmap, int x, int y,
151 unsigned int width, unsigned int height,
152 unsigned long plane_mask, int format)
153{
154 /* TODO: not sure what this function is supposed to do.. */
155 ns_retain_object (pixmap);
156 return pixmap;
157}
158
159/* Use with images created by ns_image_for_XPM. */ 147/* Use with images created by ns_image_for_XPM. */
160unsigned long 148unsigned long
161XGetPixel (XImagePtr ximage, int x, int y) 149XGetPixel (XImagePtr ximage, int x, int y)
@@ -435,8 +423,24 @@ static bool x_create_x_image_and_pixmap (struct frame *, int, int, int,
435 XImagePtr *, Pixmap *); 423 XImagePtr *, Pixmap *);
436static void x_destroy_x_image (XImagePtr ximg); 424static void x_destroy_x_image (XImagePtr ximg);
437 425
426#ifdef HAVE_NTGUI
427static XImagePtr_or_DC image_get_x_image_or_dc (struct frame *, struct image *,
428 bool, HGDIOBJ *);
429static void image_unget_x_image_or_dc (struct image *, bool, XImagePtr_or_DC,
430 HGDIOBJ);
431#else
432static XImagePtr image_get_x_image (struct frame *, struct image *, bool);
433static void image_unget_x_image (struct image *, bool, XImagePtr);
434#define image_get_x_image_or_dc(f, img, mask_p, dummy) \
435 image_get_x_image (f, img, mask_p)
436#define image_unget_x_image_or_dc(img, mask_p, ximg, dummy) \
437 image_unget_x_image (img, mask_p, ximg)
438#endif
439
438#ifdef HAVE_X_WINDOWS 440#ifdef HAVE_X_WINDOWS
439 441
442static void image_sync_to_pixmaps (struct frame *, struct image *);
443
440/* Useful functions defined in the section 444/* Useful functions defined in the section
441 `Image type independent image structures' below. */ 445 `Image type independent image structures' below. */
442 446
@@ -1050,6 +1054,14 @@ prepare_image_for_display (struct frame *f, struct image *img)
1050 if (img->pixmap == NO_PIXMAP && !img->load_failed_p) 1054 if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
1051 img->load_failed_p = ! img->type->load (f, img); 1055 img->load_failed_p = ! img->type->load (f, img);
1052 1056
1057#ifdef HAVE_X_WINDOWS
1058 if (!img->load_failed_p)
1059 {
1060 block_input ();
1061 image_sync_to_pixmaps (f, img);
1062 unblock_input ();
1063 }
1064#endif
1053} 1065}
1054 1066
1055 1067
@@ -1145,25 +1157,16 @@ four_corners_best (XImagePtr_or_DC ximg, int *corners,
1145 1157
1146#ifdef HAVE_NTGUI 1158#ifdef HAVE_NTGUI
1147 1159
1148#define Destroy_Image(img_dc, prev) \
1149 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1150
1151#define Free_Pixmap(display, pixmap) \ 1160#define Free_Pixmap(display, pixmap) \
1152 DeleteObject (pixmap) 1161 DeleteObject (pixmap)
1153 1162
1154#elif defined (HAVE_NS) 1163#elif defined (HAVE_NS)
1155 1164
1156#define Destroy_Image(ximg, dummy) \
1157 ns_release_object (ximg)
1158
1159#define Free_Pixmap(display, pixmap) \ 1165#define Free_Pixmap(display, pixmap) \
1160 ns_release_object (pixmap) 1166 ns_release_object (pixmap)
1161 1167
1162#else 1168#else
1163 1169
1164#define Destroy_Image(ximg, dummy) \
1165 XDestroyImage (ximg)
1166
1167#define Free_Pixmap(display, pixmap) \ 1170#define Free_Pixmap(display, pixmap) \
1168 XFreePixmap (display, pixmap) 1171 XFreePixmap (display, pixmap)
1169 1172
@@ -1187,22 +1190,12 @@ image_background (struct image *img, struct frame *f, XImagePtr_or_DC ximg)
1187#endif /* HAVE_NTGUI */ 1190#endif /* HAVE_NTGUI */
1188 1191
1189 if (free_ximg) 1192 if (free_ximg)
1190 { 1193 ximg = image_get_x_image_or_dc (f, img, 0, &prev);
1191#ifndef HAVE_NTGUI
1192 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
1193 0, 0, img->width, img->height, ~0, ZPixmap);
1194#else
1195 HDC frame_dc = get_frame_dc (f);
1196 ximg = CreateCompatibleDC (frame_dc);
1197 release_frame_dc (f, frame_dc);
1198 prev = SelectObject (ximg, img->pixmap);
1199#endif /* !HAVE_NTGUI */
1200 }
1201 1194
1202 img->background = four_corners_best (ximg, img->corners, img->width, img->height); 1195 img->background = four_corners_best (ximg, img->corners, img->width, img->height);
1203 1196
1204 if (free_ximg) 1197 if (free_ximg)
1205 Destroy_Image (ximg, prev); 1198 image_unget_x_image_or_dc (img, 0, ximg, prev);
1206 1199
1207 img->background_valid = 1; 1200 img->background_valid = 1;
1208 } 1201 }
@@ -1228,23 +1221,13 @@ image_background_transparent (struct image *img, struct frame *f, XImagePtr_or_D
1228#endif /* HAVE_NTGUI */ 1221#endif /* HAVE_NTGUI */
1229 1222
1230 if (free_mask) 1223 if (free_mask)
1231 { 1224 mask = image_get_x_image_or_dc (f, img, 1, &prev);
1232#ifndef HAVE_NTGUI
1233 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
1234 0, 0, img->width, img->height, ~0, ZPixmap);
1235#else
1236 HDC frame_dc = get_frame_dc (f);
1237 mask = CreateCompatibleDC (frame_dc);
1238 release_frame_dc (f, frame_dc);
1239 prev = SelectObject (mask, img->mask);
1240#endif /* HAVE_NTGUI */
1241 }
1242 1225
1243 img->background_transparent 1226 img->background_transparent
1244 = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN); 1227 = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN);
1245 1228
1246 if (free_mask) 1229 if (free_mask)
1247 Destroy_Image (mask, prev); 1230 image_unget_x_image_or_dc (img, 1, mask, prev);
1248 } 1231 }
1249 else 1232 else
1250 img->background_transparent = 0; 1233 img->background_transparent = 0;
@@ -1260,30 +1243,58 @@ image_background_transparent (struct image *img, struct frame *f, XImagePtr_or_D
1260 Helper functions for X image types 1243 Helper functions for X image types
1261 ***********************************************************************/ 1244 ***********************************************************************/
1262 1245
1263/* Clear X resources of image IMG on frame F. PIXMAP_P means free the 1246/* Clear X resources of image IMG on frame F according to FLAGS.
1264 pixmap if any. MASK_P means clear the mask pixmap if any. 1247 FLAGS is bitwise-or of the following masks:
1265 COLORS_P means free colors allocated for the image, if any. */ 1248 CLEAR_IMAGE_PIXMAP free the pixmap if any.
1249 CLEAR_IMAGE_MASK means clear the mask pixmap if any.
1250 CLEAR_IMAGE_COLORS means free colors allocated for the image, if
1251 any. */
1252
1253#define CLEAR_IMAGE_PIXMAP (1 << 0)
1254#define CLEAR_IMAGE_MASK (1 << 1)
1255#define CLEAR_IMAGE_COLORS (1 << 2)
1266 1256
1267static void 1257static void
1268x_clear_image_1 (struct frame *f, struct image *img, bool pixmap_p, 1258x_clear_image_1 (struct frame *f, struct image *img, int flags)
1269 bool mask_p, bool colors_p)
1270{ 1259{
1271 if (pixmap_p && img->pixmap) 1260 if (flags & CLEAR_IMAGE_PIXMAP)
1272 { 1261 {
1273 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap); 1262 if (img->pixmap)
1274 img->pixmap = NO_PIXMAP; 1263 {
1275 /* NOTE (HAVE_NS): background color is NOT an indexed color! */ 1264 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
1276 img->background_valid = 0; 1265 img->pixmap = NO_PIXMAP;
1266 /* NOTE (HAVE_NS): background color is NOT an indexed color! */
1267 img->background_valid = 0;
1268 }
1269#ifdef HAVE_X_WINDOWS
1270 if (img->ximg)
1271 {
1272 x_destroy_x_image (img->ximg);
1273 img->ximg = NULL;
1274 img->background_valid = 0;
1275 }
1276#endif
1277 } 1277 }
1278 1278
1279 if (mask_p && img->mask) 1279 if (flags & CLEAR_IMAGE_MASK)
1280 { 1280 {
1281 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask); 1281 if (img->mask)
1282 img->mask = NO_PIXMAP; 1282 {
1283 img->background_transparent_valid = 0; 1283 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1284 img->mask = NO_PIXMAP;
1285 img->background_transparent_valid = 0;
1286 }
1287#ifdef HAVE_X_WINDOWS
1288 if (img->mask_img)
1289 {
1290 x_destroy_x_image (img->mask_img);
1291 img->mask_img = NULL;
1292 img->background_transparent_valid = 0;
1293 }
1294#endif
1284 } 1295 }
1285 1296
1286 if (colors_p && img->ncolors) 1297 if ((flags & CLEAR_IMAGE_COLORS) && img->ncolors)
1287 { 1298 {
1288 /* W32_TODO: color table support. */ 1299 /* W32_TODO: color table support. */
1289#ifdef HAVE_X_WINDOWS 1300#ifdef HAVE_X_WINDOWS
@@ -1302,7 +1313,8 @@ static void
1302x_clear_image (struct frame *f, struct image *img) 1313x_clear_image (struct frame *f, struct image *img)
1303{ 1314{
1304 block_input (); 1315 block_input ();
1305 x_clear_image_1 (f, img, 1, 1, 1); 1316 x_clear_image_1 (f, img,
1317 CLEAR_IMAGE_PIXMAP | CLEAR_IMAGE_MASK | CLEAR_IMAGE_COLORS);
1306 unblock_input (); 1318 unblock_input ();
1307} 1319}
1308 1320
@@ -1633,10 +1645,7 @@ postprocess_image (struct frame *f, struct image *img)
1633 x_build_heuristic_mask (f, img, XCDR (mask)); 1645 x_build_heuristic_mask (f, img, XCDR (mask));
1634 } 1646 }
1635 else if (NILP (mask) && found_p && img->mask) 1647 else if (NILP (mask) && found_p && img->mask)
1636 { 1648 x_clear_image_1 (f, img, CLEAR_IMAGE_MASK);
1637 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1638 img->mask = NO_PIXMAP;
1639 }
1640 } 1649 }
1641 1650
1642 1651
@@ -2094,6 +2103,130 @@ x_put_x_image (struct frame *f, XImagePtr ximg, Pixmap pixmap, int width, int he
2094#endif 2103#endif
2095} 2104}
2096 2105
2106/* Thin wrapper for x_create_x_image_and_pixmap, so that it matches
2107 with image_put_x_image. */
2108
2109static bool
2110image_create_x_image_and_pixmap (struct frame *f, struct image *img,
2111 int width, int height, int depth,
2112 XImagePtr *ximg, bool mask_p)
2113{
2114 eassert ((!mask_p ? img->pixmap : img->mask) == NO_PIXMAP);
2115
2116 return x_create_x_image_and_pixmap (f, width, height, depth, ximg,
2117 !mask_p ? &img->pixmap : &img->mask);
2118}
2119
2120/* Put X image XIMG into image IMG on frame F, as a mask if and only
2121 if MASK_P. On X, this simply records XIMG on a member of IMG, so
2122 it can be put into the pixmap afterwards via image_sync_to_pixmaps.
2123 On the other platforms, it puts XIMG into the pixmap, then frees
2124 the X image and its buffer. */
2125
2126static void
2127image_put_x_image (struct frame *f, struct image *img, XImagePtr ximg,
2128 bool mask_p)
2129{
2130#ifdef HAVE_X_WINDOWS
2131 if (!mask_p)
2132 {
2133 eassert (img->ximg == NULL);
2134 img->ximg = ximg;
2135 }
2136 else
2137 {
2138 eassert (img->mask_img == NULL);
2139 img->mask_img = ximg;
2140 }
2141#else
2142 x_put_x_image (f, ximg, !mask_p ? img->pixmap : img->mask,
2143 img->width, img->height);
2144 x_destroy_x_image (ximg);
2145#endif
2146}
2147
2148#ifdef HAVE_X_WINDOWS
2149/* Put the X images recorded in IMG on frame F into pixmaps, then free
2150 the X images and their buffers. */
2151
2152static void
2153image_sync_to_pixmaps (struct frame *f, struct image *img)
2154{
2155 if (img->ximg)
2156 {
2157 x_put_x_image (f, img->ximg, img->pixmap, img->width, img->height);
2158 x_destroy_x_image (img->ximg);
2159 img->ximg = NULL;
2160 }
2161 if (img->mask_img)
2162 {
2163 x_put_x_image (f, img->mask_img, img->mask, img->width, img->height);
2164 x_destroy_x_image (img->mask_img);
2165 img->mask_img = NULL;
2166 }
2167}
2168#endif
2169
2170#ifdef HAVE_NTGUI
2171/* Create a memory device context for IMG on frame F. It stores the
2172 currently selected GDI object into *PREV for future restoration by
2173 image_unget_x_image_or_dc. */
2174
2175static XImagePtr_or_DC
2176image_get_x_image_or_dc (struct frame *f, struct image *img, bool mask_p,
2177 HGDIOBJ *prev)
2178{
2179 HDC frame_dc = get_frame_dc (f);
2180 XImagePtr_or_DC ximg = CreateCompatibleDC (frame_dc);
2181
2182 release_frame_dc (f, frame_dc);
2183 *prev = SelectObject (ximg, !mask_p ? img->pixmap : img->mask);
2184}
2185
2186static void image_unget_x_image_or_dc (struct frame *img, bool mask_p,
2187 XImagePtr_or_DC ximg, HGDIOBJ prev)
2188{
2189 SelectObject (ximg, prev);
2190 DeleteDC (ximg);
2191}
2192#else /* !HAVE_NTGUI */
2193/* Get the X image for IMG on frame F. The resulting X image data
2194 should be treated as read-only at least on X. */
2195
2196static XImagePtr
2197image_get_x_image (struct frame *f, struct image *img, bool mask_p)
2198{
2199#ifdef HAVE_X_WINDOWS
2200 XImagePtr ximg_in_img = !mask_p ? img->ximg : img->mask_img;
2201
2202 if (ximg_in_img)
2203 return ximg_in_img;
2204 else
2205 return XGetImage (FRAME_X_DISPLAY (f), !mask_p ? img->pixmap : img->mask,
2206 0, 0, img->width, img->height, ~0, ZPixmap);
2207#elif defined (HAVE_NS)
2208 XImagePtr pixmap = !mask_p ? img->pixmap : img->mask;
2209
2210 ns_retain_object (pixmap);
2211 return pixmap;
2212#endif
2213}
2214
2215static void image_unget_x_image (struct image *img, bool mask_p, XImagePtr ximg)
2216{
2217#ifdef HAVE_X_WINDOWS
2218 XImagePtr ximg_in_img = !mask_p ? img->ximg : img->mask_img;
2219
2220 if (ximg_in_img)
2221 eassert (ximg == ximg_in_img);
2222 else
2223 XDestroyImage (ximg);
2224#elif defined (HAVE_NS)
2225 ns_release_object (ximg);
2226#endif
2227}
2228#endif /* !HAVE_NTGUI */
2229
2097 2230
2098/*********************************************************************** 2231/***********************************************************************
2099 File Handling 2232 File Handling
@@ -3461,9 +3594,9 @@ xpm_load (struct frame *f, struct image *img)
3461 &xpm_image, &xpm_mask, 3594 &xpm_image, &xpm_mask,
3462 &attrs); 3595 &attrs);
3463#else 3596#else
3464 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3597 rc = XpmReadFileToImage (FRAME_X_DISPLAY (f), SSDATA (file),
3465 SSDATA (file), &img->pixmap, &img->mask, 3598 &img->ximg, &img->mask_img,
3466 &attrs); 3599 &attrs);
3467#endif /* HAVE_NTGUI */ 3600#endif /* HAVE_NTGUI */
3468 } 3601 }
3469 else 3602 else
@@ -3484,13 +3617,38 @@ xpm_load (struct frame *f, struct image *img)
3484 &xpm_image, &xpm_mask, 3617 &xpm_image, &xpm_mask,
3485 &attrs); 3618 &attrs);
3486#else 3619#else
3487 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3620 rc = XpmCreateImageFromBuffer (FRAME_X_DISPLAY (f), SSDATA (buffer),
3488 SSDATA (buffer), 3621 &img->ximg, &img->mask_img,
3489 &img->pixmap, &img->mask, 3622 &attrs);
3490 &attrs);
3491#endif /* HAVE_NTGUI */ 3623#endif /* HAVE_NTGUI */
3492 } 3624 }
3493 3625
3626#ifdef HAVE_X_WINDOWS
3627 if (rc == XpmSuccess)
3628 {
3629 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3630 img->ximg->width, img->ximg->height,
3631 img->ximg->depth);
3632 if (img->pixmap == NO_PIXMAP)
3633 {
3634 x_clear_image (f, img);
3635 rc = XpmNoMemory;
3636 }
3637 else if (img->mask_img)
3638 {
3639 img->mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3640 img->mask_img->width,
3641 img->mask_img->height,
3642 img->mask_img->depth);
3643 if (img->mask == NO_PIXMAP)
3644 {
3645 x_clear_image (f, img);
3646 rc = XpmNoMemory;
3647 }
3648 }
3649 }
3650#endif
3651
3494 if (rc == XpmSuccess) 3652 if (rc == XpmSuccess)
3495 { 3653 {
3496#if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS) 3654#if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
@@ -3549,6 +3707,15 @@ xpm_load (struct frame *f, struct image *img)
3549#else 3707#else
3550 XpmFreeAttributes (&attrs); 3708 XpmFreeAttributes (&attrs);
3551#endif /* HAVE_NTGUI */ 3709#endif /* HAVE_NTGUI */
3710
3711#ifdef HAVE_X_WINDOWS
3712 /* Maybe fill in the background field while we have ximg handy. */
3713 IMAGE_BACKGROUND (img, f, img->ximg);
3714 if (img->mask_img)
3715 /* Fill in the background_transparent field while we have the
3716 mask handy. */
3717 image_background_transparent (img, f, img->mask_img);
3718#endif
3552 } 3719 }
3553 else 3720 else
3554 { 3721 {
@@ -3847,11 +4014,10 @@ xpm_load_image (struct frame *f,
3847 goto failure; 4014 goto failure;
3848 } 4015 }
3849 4016
3850 if (!x_create_x_image_and_pixmap (f, width, height, 0, 4017 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)
3851 &ximg, &img->pixmap)
3852#ifndef HAVE_NS 4018#ifndef HAVE_NS
3853 || !x_create_x_image_and_pixmap (f, width, height, 1, 4019 || !image_create_x_image_and_pixmap (f, img, width, height, 1,
3854 &mask_img, &img->mask) 4020 &mask_img, 1)
3855#endif 4021#endif
3856 ) 4022 )
3857 { 4023 {
@@ -3986,8 +4152,7 @@ xpm_load_image (struct frame *f,
3986 if (NILP (image_spec_value (img->spec, QCbackground, NULL))) 4152 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
3987 IMAGE_BACKGROUND (img, f, ximg); 4153 IMAGE_BACKGROUND (img, f, ximg);
3988 4154
3989 x_put_x_image (f, ximg, img->pixmap, width, height); 4155 image_put_x_image (f, img, ximg, 0);
3990 x_destroy_x_image (ximg);
3991#ifndef HAVE_NS 4156#ifndef HAVE_NS
3992 if (have_mask) 4157 if (have_mask)
3993 { 4158 {
@@ -3995,14 +4160,12 @@ xpm_load_image (struct frame *f,
3995 mask handy. */ 4160 mask handy. */
3996 image_background_transparent (img, f, mask_img); 4161 image_background_transparent (img, f, mask_img);
3997 4162
3998 x_put_x_image (f, mask_img, img->mask, width, height); 4163 image_put_x_image (f, img, mask_img, 1);
3999 x_destroy_x_image (mask_img);
4000 } 4164 }
4001 else 4165 else
4002 { 4166 {
4003 x_destroy_x_image (mask_img); 4167 x_destroy_x_image (mask_img);
4004 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask); 4168 x_clear_image_1 (f, img, CLEAR_IMAGE_MASK);
4005 img->mask = NO_PIXMAP;
4006 } 4169 }
4007#endif 4170#endif
4008 return 1; 4171 return 1;
@@ -4400,17 +4563,8 @@ x_to_xcolors (struct frame *f, struct image *img, bool rgb_p)
4400 memory_full (SIZE_MAX); 4563 memory_full (SIZE_MAX);
4401 colors = xmalloc (sizeof *colors * img->width * img->height); 4564 colors = xmalloc (sizeof *colors * img->width * img->height);
4402 4565
4403#ifndef HAVE_NTGUI 4566 /* Get the X image or create a memory device context for IMG. */
4404 /* Get the X image IMG->pixmap. */ 4567 ximg = image_get_x_image_or_dc (f, img, 0, &prev);
4405 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
4406 0, 0, img->width, img->height, ~0, ZPixmap);
4407#else
4408 /* Load the image into a memory device context. */
4409 hdc = get_frame_dc (f);
4410 ximg = CreateCompatibleDC (hdc);
4411 release_frame_dc (f, hdc);
4412 prev = SelectObject (ximg, img->pixmap);
4413#endif /* HAVE_NTGUI */
4414 4568
4415 /* Fill the `pixel' members of the XColor array. I wished there 4569 /* Fill the `pixel' members of the XColor array. I wished there
4416 were an easy and portable way to circumvent XGetPixel. */ 4570 were an easy and portable way to circumvent XGetPixel. */
@@ -4440,7 +4594,7 @@ x_to_xcolors (struct frame *f, struct image *img, bool rgb_p)
4440#endif /* HAVE_X_WINDOWS */ 4594#endif /* HAVE_X_WINDOWS */
4441 } 4595 }
4442 4596
4443 Destroy_Image (ximg, prev); 4597 image_unget_x_image_or_dc (img, 0, ximg, prev);
4444 4598
4445 return colors; 4599 return colors;
4446} 4600}
@@ -4505,8 +4659,9 @@ x_from_xcolors (struct frame *f, struct image *img, XColor *colors)
4505 4659
4506 init_color_table (); 4660 init_color_table ();
4507 4661
4508 x_create_x_image_and_pixmap (f, img->width, img->height, 0, 4662 x_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP | CLEAR_IMAGE_COLORS);
4509 &oimg, &pixmap); 4663 image_create_x_image_and_pixmap (f, img, img->width, img->height, 0,
4664 &oimg, 0);
4510 p = colors; 4665 p = colors;
4511 for (y = 0; y < img->height; ++y) 4666 for (y = 0; y < img->height; ++y)
4512 for (x = 0; x < img->width; ++x, ++p) 4667 for (x = 0; x < img->width; ++x, ++p)
@@ -4517,11 +4672,8 @@ x_from_xcolors (struct frame *f, struct image *img, XColor *colors)
4517 } 4672 }
4518 4673
4519 xfree (colors); 4674 xfree (colors);
4520 x_clear_image_1 (f, img, 1, 0, 1);
4521 4675
4522 x_put_x_image (f, oimg, pixmap, img->width, img->height); 4676 image_put_x_image (f, img, oimg, 0);
4523 x_destroy_x_image (oimg);
4524 img->pixmap = pixmap;
4525#ifdef COLOR_TABLE_SUPPORT 4677#ifdef COLOR_TABLE_SUPPORT
4526 img->colors = colors_in_color_table (&img->ncolors); 4678 img->colors = colors_in_color_table (&img->ncolors);
4527 free_color_table (); 4679 free_color_table ();
@@ -4706,7 +4858,10 @@ x_disable_image (struct frame *f, struct image *img)
4706#define MaskForeground(f) WHITE_PIX_DEFAULT (f) 4858#define MaskForeground(f) WHITE_PIX_DEFAULT (f)
4707 4859
4708 Display *dpy = FRAME_X_DISPLAY (f); 4860 Display *dpy = FRAME_X_DISPLAY (f);
4709 GC gc = XCreateGC (dpy, img->pixmap, 0, NULL); 4861 GC gc;
4862
4863 image_sync_to_pixmaps (f, img);
4864 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
4710 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f)); 4865 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
4711 XDrawLine (dpy, img->pixmap, gc, 0, 0, 4866 XDrawLine (dpy, img->pixmap, gc, 0, 0,
4712 img->width - 1, img->height - 1); 4867 img->width - 1, img->height - 1);
@@ -4781,37 +4936,25 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
4781 unsigned long bg = 0; 4936 unsigned long bg = 0;
4782 4937
4783 if (img->mask) 4938 if (img->mask)
4784 { 4939 x_clear_image_1 (f, img, CLEAR_IMAGE_MASK);
4785 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4786 img->mask = NO_PIXMAP;
4787 img->background_transparent_valid = 0;
4788 }
4789 4940
4790#ifndef HAVE_NTGUI 4941#ifndef HAVE_NTGUI
4791#ifndef HAVE_NS 4942#ifndef HAVE_NS
4792 /* Create an image and pixmap serving as mask. */ 4943 /* Create an image and pixmap serving as mask. */
4793 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1, 4944 rc = image_create_x_image_and_pixmap (f, img, img->width, img->height, 1,
4794 &mask_img, &img->mask); 4945 &mask_img, 1);
4795 if (!rc) 4946 if (!rc)
4796 return; 4947 return;
4797#endif /* !HAVE_NS */ 4948#endif /* !HAVE_NS */
4798
4799 /* Get the X image of IMG->pixmap. */
4800 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0,
4801 img->width, img->height,
4802 ~0, ZPixmap);
4803#else 4949#else
4804 /* Create the bit array serving as mask. */ 4950 /* Create the bit array serving as mask. */
4805 row_width = (img->width + 7) / 8; 4951 row_width = (img->width + 7) / 8;
4806 mask_img = xzalloc (row_width * img->height); 4952 mask_img = xzalloc (row_width * img->height);
4807
4808 /* Create a memory device context for IMG->pixmap. */
4809 frame_dc = get_frame_dc (f);
4810 ximg = CreateCompatibleDC (frame_dc);
4811 release_frame_dc (f, frame_dc);
4812 prev = SelectObject (ximg, img->pixmap);
4813#endif /* HAVE_NTGUI */ 4953#endif /* HAVE_NTGUI */
4814 4954
4955 /* Get the X image or create a memory device context for IMG. */
4956 ximg = image_get_x_image_or_dc (f, img, 0, &prev);
4957
4815 /* Determine the background color of ximg. If HOW is `(R G B)' 4958 /* Determine the background color of ximg. If HOW is `(R G B)'
4816 take that as color. Otherwise, use the image's background color. */ 4959 take that as color. Otherwise, use the image's background color. */
4817 use_img_background = 1; 4960 use_img_background = 1;
@@ -4858,9 +5001,8 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
4858 /* Fill in the background_transparent field while we have the mask handy. */ 5001 /* Fill in the background_transparent field while we have the mask handy. */
4859 image_background_transparent (img, f, mask_img); 5002 image_background_transparent (img, f, mask_img);
4860 5003
4861 /* Put mask_img into img->mask. */ 5004 /* Put mask_img into the image. */
4862 x_put_x_image (f, mask_img, img->mask, img->width, img->height); 5005 image_put_x_image (f, img, mask_img, 1);
4863 x_destroy_x_image (mask_img);
4864#endif /* !HAVE_NS */ 5006#endif /* !HAVE_NS */
4865#else 5007#else
4866 for (y = 0; y < img->height; ++y) 5008 for (y = 0; y < img->height; ++y)
@@ -4882,7 +5024,7 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
4882 xfree (mask_img); 5024 xfree (mask_img);
4883#endif /* HAVE_NTGUI */ 5025#endif /* HAVE_NTGUI */
4884 5026
4885 Destroy_Image (ximg, prev); 5027 image_unget_x_image_or_dc (img, 0, ximg, prev);
4886} 5028}
4887 5029
4888 5030
@@ -5110,8 +5252,7 @@ pbm_load (struct frame *f, struct image *img)
5110 goto error; 5252 goto error;
5111 } 5253 }
5112 5254
5113 if (!x_create_x_image_and_pixmap (f, width, height, 0, 5255 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
5114 &ximg, &img->pixmap))
5115 goto error; 5256 goto error;
5116 5257
5117 /* Initialize the color hash table. */ 5258 /* Initialize the color hash table. */
@@ -5248,9 +5389,8 @@ pbm_load (struct frame *f, struct image *img)
5248 /* Casting avoids a GCC warning. */ 5389 /* Casting avoids a GCC warning. */
5249 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg); 5390 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
5250 5391
5251 /* Put the image into a pixmap. */ 5392 /* Put ximg into the image. */
5252 x_put_x_image (f, ximg, img->pixmap, width, height); 5393 image_put_x_image (f, img, ximg, 0);
5253 x_destroy_x_image (ximg);
5254 5394
5255 /* X and W32 versions did it here, MAC version above. ++kfs 5395 /* X and W32 versions did it here, MAC version above. ++kfs
5256 img->width = width; 5396 img->width = width;
@@ -5688,8 +5828,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5688 5828
5689 /* Create the X image and pixmap now, so that the work below can be 5829 /* Create the X image and pixmap now, so that the work below can be
5690 omitted if the image is too large for X. */ 5830 omitted if the image is too large for X. */
5691 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, 5831 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
5692 &img->pixmap))
5693 goto error; 5832 goto error;
5694 5833
5695 /* If image contains simply transparency data, we prefer to 5834 /* If image contains simply transparency data, we prefer to
@@ -5801,12 +5940,11 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5801 contains an alpha channel. */ 5940 contains an alpha channel. */
5802 if (channels == 4 5941 if (channels == 4
5803 && !transparent_p 5942 && !transparent_p
5804 && !x_create_x_image_and_pixmap (f, width, height, 1, 5943 && !image_create_x_image_and_pixmap (f, img, width, height, 1,
5805 &mask_img, &img->mask)) 5944 &mask_img, 1))
5806 { 5945 {
5807 x_destroy_x_image (ximg); 5946 x_destroy_x_image (ximg);
5808 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap); 5947 x_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP);
5809 img->pixmap = NO_PIXMAP;
5810 goto error; 5948 goto error;
5811 } 5949 }
5812 5950
@@ -5880,9 +6018,8 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5880 Casting avoids a GCC warning. */ 6018 Casting avoids a GCC warning. */
5881 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg); 6019 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
5882 6020
5883 /* Put the image into the pixmap, then free the X image and its buffer. */ 6021 /* Put ximg into the image. */
5884 x_put_x_image (f, ximg, img->pixmap, width, height); 6022 image_put_x_image (f, img, ximg, 0);
5885 x_destroy_x_image (ximg);
5886 6023
5887 /* Same for the mask. */ 6024 /* Same for the mask. */
5888 if (mask_img) 6025 if (mask_img)
@@ -5891,8 +6028,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5891 mask handy. Casting avoids a GCC warning. */ 6028 mask handy. Casting avoids a GCC warning. */
5892 image_background_transparent (img, f, (XImagePtr_or_DC)mask_img); 6029 image_background_transparent (img, f, (XImagePtr_or_DC)mask_img);
5893 6030
5894 x_put_x_image (f, mask_img, img->mask, img->width, img->height); 6031 image_put_x_image (f, img, mask_img, 1);
5895 x_destroy_x_image (mask_img);
5896 } 6032 }
5897 6033
5898 return 1; 6034 return 1;
@@ -6429,7 +6565,7 @@ jpeg_load_body (struct frame *f, struct image *img,
6429 } 6565 }
6430 6566
6431 /* Create X image and pixmap. */ 6567 /* Create X image and pixmap. */
6432 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) 6568 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
6433 { 6569 {
6434 mgr->failure_code = MY_JPEG_CANNOT_CREATE_X; 6570 mgr->failure_code = MY_JPEG_CANNOT_CREATE_X;
6435 sys_longjmp (mgr->setjmp_buffer, 1); 6571 sys_longjmp (mgr->setjmp_buffer, 1);
@@ -6496,9 +6632,8 @@ jpeg_load_body (struct frame *f, struct image *img,
6496 /* Casting avoids a GCC warning. */ 6632 /* Casting avoids a GCC warning. */
6497 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg); 6633 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6498 6634
6499 /* Put the image into the pixmap. */ 6635 /* Put ximg into the image. */
6500 x_put_x_image (f, ximg, img->pixmap, width, height); 6636 image_put_x_image (f, img, ximg, 0);
6501 x_destroy_x_image (ximg);
6502 return 1; 6637 return 1;
6503} 6638}
6504 6639
@@ -6895,8 +7030,8 @@ tiff_load (struct frame *f, struct image *img)
6895 7030
6896 /* Create the X image and pixmap. */ 7031 /* Create the X image and pixmap. */
6897 if (! (height <= min (PTRDIFF_MAX, SIZE_MAX) / sizeof *buf / width 7032 if (! (height <= min (PTRDIFF_MAX, SIZE_MAX) / sizeof *buf / width
6898 && x_create_x_image_and_pixmap (f, width, height, 0, 7033 && image_create_x_image_and_pixmap (f, img, width, height, 0,
6899 &ximg, &img->pixmap))) 7034 &ximg, 0)))
6900 { 7035 {
6901 fn_TIFFClose (tiff); 7036 fn_TIFFClose (tiff);
6902 return 0; 7037 return 0;
@@ -6955,9 +7090,8 @@ tiff_load (struct frame *f, struct image *img)
6955 /* Casting avoids a GCC warning on W32. */ 7090 /* Casting avoids a GCC warning on W32. */
6956 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg); 7091 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6957 7092
6958 /* Put the image into the pixmap, then free the X image and its buffer. */ 7093 /* Put ximg into the image. */
6959 x_put_x_image (f, ximg, img->pixmap, width, height); 7094 image_put_x_image (f, img, ximg, 0);
6960 x_destroy_x_image (ximg);
6961 xfree (buf); 7095 xfree (buf);
6962 7096
6963 return 1; 7097 return 1;
@@ -7285,7 +7419,7 @@ gif_load (struct frame *f, struct image *img)
7285 } 7419 }
7286 7420
7287 /* Create the X image and pixmap. */ 7421 /* Create the X image and pixmap. */
7288 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) 7422 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
7289 { 7423 {
7290 fn_DGifCloseFile (gif); 7424 fn_DGifCloseFile (gif);
7291 return 0; 7425 return 0;
@@ -7469,9 +7603,8 @@ gif_load (struct frame *f, struct image *img)
7469 /* Casting avoids a GCC warning. */ 7603 /* Casting avoids a GCC warning. */
7470 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg); 7604 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7471 7605
7472 /* Put the image into the pixmap, then free the X image and its buffer. */ 7606 /* Put ximg into the image. */
7473 x_put_x_image (f, ximg, img->pixmap, width, height); 7607 image_put_x_image (f, img, ximg, 0);
7474 x_destroy_x_image (ximg);
7475 7608
7476 return 1; 7609 return 1;
7477} 7610}
@@ -7909,8 +8042,8 @@ imagemagick_load_image (struct frame *f, struct image *img,
7909 int imagedepth = 24; /*MagickGetImageDepth(image_wand);*/ 8042 int imagedepth = 24; /*MagickGetImageDepth(image_wand);*/
7910 const char *exportdepth = imagedepth <= 8 ? "I" : "BGRP"; /*"RGBP";*/ 8043 const char *exportdepth = imagedepth <= 8 ? "I" : "BGRP"; /*"RGBP";*/
7911 /* Try to create a x pixmap to hold the imagemagick pixmap. */ 8044 /* Try to create a x pixmap to hold the imagemagick pixmap. */
7912 if (!x_create_x_image_and_pixmap (f, width, height, imagedepth, 8045 if (!image_create_x_image_and_pixmap (f, img, width, height, imagedepth,
7913 &ximg, &img->pixmap)) 8046 &ximg, 0))
7914 { 8047 {
7915#ifdef COLOR_TABLE_SUPPORT 8048#ifdef COLOR_TABLE_SUPPORT
7916 free_color_table (); 8049 free_color_table ();
@@ -7948,8 +8081,8 @@ imagemagick_load_image (struct frame *f, struct image *img,
7948 size_t image_height; 8081 size_t image_height;
7949 8082
7950 /* Try to create a x pixmap to hold the imagemagick pixmap. */ 8083 /* Try to create a x pixmap to hold the imagemagick pixmap. */
7951 if (!x_create_x_image_and_pixmap (f, width, height, 0, 8084 if (!image_create_x_image_and_pixmap (f, img, width, height, 0,
7952 &ximg, &img->pixmap)) 8085 &ximg, 0))
7953 { 8086 {
7954#ifdef COLOR_TABLE_SUPPORT 8087#ifdef COLOR_TABLE_SUPPORT
7955 free_color_table (); 8088 free_color_table ();
@@ -8003,10 +8136,8 @@ imagemagick_load_image (struct frame *f, struct image *img,
8003 img->width = width; 8136 img->width = width;
8004 img->height = height; 8137 img->height = height;
8005 8138
8006 /* Put the image into the pixmap, then free the X image and its 8139 /* Put ximg into the image. */
8007 buffer. */ 8140 image_put_x_image (f, img, ximg, 0);
8008 x_put_x_image (f, ximg, img->pixmap, width, height);
8009 x_destroy_x_image (ximg);
8010 8141
8011 /* Final cleanup. image_wand should be the only resource left. */ 8142 /* Final cleanup. image_wand should be the only resource left. */
8012 DestroyMagickWand (image_wand); 8143 DestroyMagickWand (image_wand);
@@ -8400,7 +8531,7 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. *
8400 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf) == 8); 8531 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
8401 8532
8402 /* Try to create a x pixmap to hold the svg pixmap. */ 8533 /* Try to create a x pixmap to hold the svg pixmap. */
8403 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) 8534 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
8404 { 8535 {
8405 fn_g_object_unref (pixbuf); 8536 fn_g_object_unref (pixbuf);
8406 return 0; 8537 return 0;
@@ -8475,10 +8606,8 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. *
8475 Casting avoids a GCC warning. */ 8606 Casting avoids a GCC warning. */
8476 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg); 8607 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
8477 8608
8478 /* Put the image into the pixmap, then free the X image and its 8609 /* Put ximg into the image. */
8479 buffer. */ 8610 image_put_x_image (f, img, ximg, 0);
8480 x_put_x_image (f, ximg, img->pixmap, width, height);
8481 x_destroy_x_image (ximg);
8482 8611
8483 return 1; 8612 return 1;
8484 8613